// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use super::*; use alloc::vec::Vec; type MapF = fn(&(K, V)) -> (&K, &V); #[inline] fn map_f(input: &(K, V)) -> (&K, &V) { (&input.0, &input.1) } type MapFMut = fn(&mut (K, V)) -> (&K, &mut V); #[inline] fn map_f_mut(input: &mut (K, V)) -> (&K, &mut V) { (&input.0, &mut input.1) } impl StoreConstEmpty for Vec<(K, V)> { const EMPTY: Vec<(K, V)> = Vec::new(); } impl Store for Vec<(K, V)> { #[inline] fn lm_len(&self) -> usize { self.as_slice().len() } #[inline] fn lm_is_empty(&self) -> bool { self.as_slice().is_empty() } #[inline] fn lm_get(&self, index: usize) -> Option<(&K, &V)> { self.as_slice().get(index).map(map_f) } #[inline] fn lm_last(&self) -> Option<(&K, &V)> { self.as_slice().last().map(map_f) } #[inline] fn lm_binary_search_by(&self, mut cmp: F) -> Result where F: FnMut(&K) -> Ordering, { self.as_slice().binary_search_by(|(k, _)| cmp(k)) } } impl StoreSlice for Vec<(K, V)> { type Slice = [(K, V)]; fn lm_get_range(&self, range: Range) -> Option<&Self::Slice> { self.get(range) } } impl StoreMut for Vec<(K, V)> { #[inline] fn lm_with_capacity(capacity: usize) -> Self { Self::with_capacity(capacity) } #[inline] fn lm_reserve(&mut self, additional: usize) { self.reserve(additional) } #[inline] fn lm_get_mut(&mut self, index: usize) -> Option<(&K, &mut V)> { self.as_mut_slice().get_mut(index).map(map_f_mut) } #[inline] fn lm_push(&mut self, key: K, value: V) { self.push((key, value)) } #[inline] fn lm_insert(&mut self, index: usize, key: K, value: V) { self.insert(index, (key, value)) } #[inline] fn lm_remove(&mut self, index: usize) -> (K, V) { self.remove(index) } #[inline] fn lm_clear(&mut self) { self.clear() } } impl StoreBulkMut for Vec<(K, V)> { #[inline] fn lm_retain(&mut self, mut predicate: F) where F: FnMut(&K, &V) -> bool, { self.retain(|(k, v)| predicate(k, v)) } /// Extends this store with items from an iterator. /// /// It uses a two-pass (sort + dedup) approach to avoid any potential quadratic costs. /// /// The asymptotic worst case complexity is O((n + m) log(n + m)), where `n` /// is the number of elements already in `self` and `m` is the number of elements /// in the iterator. The best case complexity is O(m), when the input iterator is /// already sorted, keys aren't duplicated and all keys sort after the existing ones. #[inline] fn lm_extend(&mut self, iter: I) where I: IntoIterator, K: Ord, { // First N elements in self that are already sorted and not duplicated. let mut sorted_len = self.len(); // Use Vec::extend as it has a specialized code for slice and trusted-len iterators. self.extend(iter); // `sorted_len` is the length of the sorted run before extension // window slice `w` is guaranteed to have a length of 2. #[allow(clippy::indexing_slicing)] { // Count new elements that are sorted and non-duplicated. // Starting from the end of the existing sorted run, if any. // Thus, start the slice at sorted_len.saturating_sub(1). sorted_len += self[sorted_len.saturating_sub(1)..] .windows(2) .take_while(|w| w[0].0 < w[1].0) .count(); } // `windows(2)` only yields `slice len - 1` times, or none if the slice is empty. // In other words, the first extended element of the slice won't be counted as sorted // if self was initially empty (sorted_len == 0). We adjust this by adding 1 if the // original slice was empty but became not empty after extend. sorted_len += (sorted_len == 0 && !self.is_empty()) as usize; // If everything was in order, we're done if sorted_len >= self.len() { return; } // Use stable sort to keep relative order of duplicates. self.sort_by(|a, b| a.0.cmp(&b.0)); // Deduplicate by keeping the last element of the run in the first slice. let (dedup, _merged_dup) = partition_dedup_by(self); sorted_len = dedup.len(); self.truncate(sorted_len); } } /// Moves all but the _last_ of consecutive elements to the end of the slice satisfying /// equality on K. /// /// Returns two slices. The first contains no consecutive repeated elements. /// The second contains all the duplicates in no specified order. /// /// This is based on std::slice::partition_dedup_by (currently unstable) but retains the /// _last_ element of the duplicate run in the first slice (instead of first). #[inline] #[allow(clippy::type_complexity)] fn partition_dedup_by(v: &mut [(K, V)]) -> (&mut [(K, V)], &mut [(K, V)]) { // Although we have a mutable reference to `self`, we cannot make // *arbitrary* changes. The comparison could panic, so we // must ensure that the slice is in a valid state at all times. // // The way that we handle this is by using swaps; we iterate // over all the elements, swapping as we go so that at the end // the elements we wish to keep are in the front, and those we // wish to reject are at the back. We can then split the slice. // This operation is still `O(n)`. // // Example: // Assume (K, V) is (char, u8): // // We start in this state, where `r` represents "next // read" and `w` represents "next_write". // // r // | a,0 | b,0 | b,1 | c,0 | d,0 | d,1 | // w // // Comparing self[r] against self[w-1], this is not a duplicate, so // we swap self[r] and self[w] (no effect as r==w) and then increment both // r and w, leaving us with: // // r // | a,0 | b,0 | b,1 | c,0 | d,0 | d,0 | // w // // Comparing self[r] against self[w-1], this value is a duplicate, // we swap self[r] and self[w-1] and then increment `r`: // // r // | a,0 | b,1 | b,0 | c,0 | d,0 | d,1 | // w // // Comparing self[r] against self[w-1], this is not a duplicate, // so swap self[r] and self[w] and advance r and w: // // r // | a,0 | b,1 | c,0 | b,0 | d,0 | d,1 | // w // // Comparing self[r] against self[w-1], this is not a duplicate, // so swap self[r] and self[w] and advance r and w: // // r // | a,0 | b,1 | c,0 | d,0 | b,0 | d,1 | // w // // Comparing self[r] against self[w-1], this value is a duplicate, // we swap self[r] and self[w-1] and then increment `r`: // r // | a,0 | b,1 | c,0 | d,1 | b,0 | d,0 | // w // // End of slice, as r > len. Split at w. if v.len() <= 1 { return (v, &mut []); } let mut read_idx: usize = 1; let mut write_idx: usize = 1; while let Some((before_read, [read, ..])) = v.split_at_mut_checked(read_idx) { // First, `read_idx >= write_idx` is always true as `read_idx` is always incremented // whereas `write_idx` is only incremented when a distinct element is found. // Second, before_read is always at least 1 length due to read_idx being initialized to 1. // Thus it is safe to index before_read with `write_idx - 1`. #[allow(clippy::indexing_slicing)] let prev_write = &mut before_read[write_idx - 1]; if read.0 == prev_write.0 { core::mem::swap(read, prev_write); } else { // Equivalent to checking if write_idx == read_idx if let Some(write) = before_read.get_mut(write_idx) { core::mem::swap(read, write); } write_idx += 1; } read_idx += 1; } v.split_at_mut(write_idx) } impl StoreFromIterable for Vec<(K, V)> { fn lm_sort_from_iter>(iter: I) -> Self { let mut v = Self::new(); v.lm_extend(iter); v } } impl<'a, K: 'a, V: 'a> StoreIterable<'a, K, V> for Vec<(K, V)> { type KeyValueIter = core::iter::Map, MapF>; #[inline] fn lm_iter(&'a self) -> Self::KeyValueIter { self.as_slice().iter().map(map_f) } } impl<'a, K: 'a, V: 'a> StoreIterableMut<'a, K, V> for Vec<(K, V)> { type KeyValueIterMut = core::iter::Map, MapFMut>; #[inline] fn lm_iter_mut(&'a mut self) -> Self::KeyValueIterMut { self.as_mut_slice().iter_mut().map(map_f_mut) } } impl StoreIntoIterator for Vec<(K, V)> { type KeyValueIntoIter = alloc::vec::IntoIter<(K, V)>; #[inline] fn lm_into_iter(self) -> Self::KeyValueIntoIter { IntoIterator::into_iter(self) } #[inline] fn lm_extend_end(&mut self, other: Self) { self.extend(other) } #[inline] fn lm_extend_start(&mut self, other: Self) { self.splice(0..0, other); } } impl StoreFromIterator for Vec<(K, V)> {} #[test] fn test_vec_impl() { crate::testing::check_store_full::>(); }