diff --git a/src/lib.rs b/src/lib.rs index ff4407a..dc24f27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,11 +17,18 @@ mod macros; mod keyed; pub mod map; pub mod set; +mod sorted_keyed; +pub mod sorted_map; +pub mod sorted_set; #[doc(inline)] pub use self::map::VecMap; #[doc(inline)] pub use self::set::VecSet; +#[doc(inline)] +pub use self::sorted_map::SortedVecMap; +#[doc(inline)] +pub use self::sorted_set::SortedVecSet; pub use alloc::collections::TryReserveError; use alloc::vec::Vec; diff --git a/src/macros.rs b/src/macros.rs index 1eda6a4..b207561 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -64,3 +64,4 @@ macro_rules! vecset { } }; } + diff --git a/src/sorted_keyed.rs b/src/sorted_keyed.rs new file mode 100644 index 0000000..1523dd0 --- /dev/null +++ b/src/sorted_keyed.rs @@ -0,0 +1,511 @@ +//! Internal backing type for `SortedVecMap` and `SortedVecSet`. +//! +//! This module provides `SortedKeyedVecSet`, a generic ordered collection that keeps its +//! elements sorted by key and uses binary search for lookups. It reuses the [`Keyed`] trait from +//! [`crate::keyed`]. + +mod impls; + +use crate::TryReserveError; +use crate::keyed::Keyed; +use alloc::vec::{self, Vec}; +use core::borrow::Borrow; +use core::mem; +use core::ops::{Bound, RangeBounds}; + +/// A vector-based collection which keeps its elements sorted by key. +/// +/// Internally it is represented as a `Vec` whose elements are always kept sorted by the key +/// extracted via [`Keyed::key`]. This design allows any data type to be used as an element of +/// `SortedKeyedVecSet`, as long as it contains data that can be considered as a key and that key +/// is [`Ord`]. +/// +/// When `V = T` (where `T: Keyed`), `SortedKeyedVecSet` is equivalent to +/// [`SortedVecSet`](crate::SortedVecSet). +/// When `V = Slot`, `SortedKeyedVecSet>` is equivalent to +/// [`SortedVecMap`](crate::SortedVecMap). +#[derive(Clone, Debug)] +pub(crate) struct SortedKeyedVecSet { + base: Vec, + _marker: core::marker::PhantomData, +} + +impl SortedKeyedVecSet { + /// Create a new set. (Does not allocate.) + pub const fn new() -> Self { + SortedKeyedVecSet { + base: Vec::new(), + _marker: core::marker::PhantomData, + } + } + + /// Create a new set with capacity for `capacity` elements. (Does not allocate if `capacity` + /// is zero.) + pub fn with_capacity(capacity: usize) -> Self { + SortedKeyedVecSet { + base: Vec::with_capacity(capacity), + _marker: core::marker::PhantomData, + } + } + + /// Returns the number of elements the set can hold without reallocating. + pub fn capacity(&self) -> usize { + self.base.capacity() + } + + /// Returns the number of elements in the set. + pub fn len(&self) -> usize { + self.base.len() + } + + /// Returns `true` if the set contains no elements. + pub fn is_empty(&self) -> bool { + self.base.is_empty() + } + + /// Clears the set, removing all elements. + pub fn clear(&mut self) { + self.base.clear(); + } + + /// Shortens the set, keeping the first `len` elements and dropping the rest. + /// + /// If `len` is greater than the set's current length, this has no effect. + pub fn truncate(&mut self, len: usize) { + self.base.truncate(len); + } + + /// Reserves capacity for at least `additional` more elements to be inserted. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + pub fn reserve(&mut self, additional: usize) { + self.base.reserve(additional); + } + + /// Reserves the minimum capacity for at least `additional` more elements to be inserted. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + pub fn reserve_exact(&mut self, additional: usize) { + self.base.reserve_exact(additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` more elements to be + /// inserted. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve_exact(additional) + } + + /// Shrinks the capacity of the set as much as possible. + pub fn shrink_to_fit(&mut self) { + self.base.shrink_to_fit(); + } + + /// Shrinks the capacity of the set with a lower limit. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + pub fn shrink_to(&mut self, min_capacity: usize) { + self.base.shrink_to(min_capacity); + } + + /// Splits the set into two at the given index. + /// + /// Returns a newly allocated set containing the elements in the range `[at, len)`. After the + /// call, the original set will be left containing the elements `[0, at)` with its previous + /// capacity unchanged. + /// + /// # Panics + /// + /// Panics if `at > len`. + pub fn split_off(&mut self, at: usize) -> SortedKeyedVecSet { + SortedKeyedVecSet { + base: self.base.split_off(at), + _marker: core::marker::PhantomData, + } + } + + /// Removes the specified range from the vector in bulk, returning all removed elements as an + /// iterator. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if the end point is greater + /// than the length of the vector. + pub fn drain(&mut self, range: R) -> vec::Drain<'_, V> + where + R: RangeBounds, + { + self.base.drain(range) + } + + /// Retains only the elements specified by the predicate. + /// + /// Because the predicate cannot observe keys separately from values it cannot invalidate the + /// sort invariant. + pub fn retain(&mut self, f: F) + where + F: FnMut(&V) -> bool, + { + self.base.retain(f); + } + + /// Retains only the elements specified by the predicate, with mutable access. + /// + /// # Safety considerations + /// + /// The caller must not mutate the key portion of the element in a way that would invalidate + /// the sort order. In practice this method is only exposed to callers that hand out + /// `&mut value` (not `&mut key`). + pub fn retain_mut(&mut self, f: F) + where + F: FnMut(&mut V) -> bool, + { + self.base.retain_mut(f); + } + + /// Extracts a slice containing the set elements. + pub fn as_slice(&self) -> &[V] { + self.base.as_slice() + } + + /// Extracts a mutable slice containing the set elements. + /// + /// The caller must not mutate the key portion of any element in a way that would invalidate + /// the sort order. + pub fn as_mut_slice(&mut self) -> &mut [V] { + self.base.as_mut_slice() + } + + /// Copies the set elements into a new `Vec`. + pub fn to_vec(&self) -> Vec + where + V: Clone, + { + self.base.clone() + } + + /// Takes ownership of the set and returns its elements as a `Vec`. + pub fn into_vec(self) -> Vec { + self.base + } + + /// Takes ownership of the provided vector and converts it into `SortedKeyedVecSet`. + /// + /// # Safety + /// + /// The vector must be sorted strictly by key (no duplicate keys). One way to guarantee this + /// is to sort the vector (e.g. by using [`[T]::sort_by`][slice-sort-by]) and then drop + /// duplicate keys (e.g. by using [`Vec::dedup_by`]). + /// + /// [slice-sort-by]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by + pub unsafe fn from_vec_unchecked(base: Vec) -> Self { + SortedKeyedVecSet { + base, + _marker: core::marker::PhantomData, + } + } +} + +// Lookup operations +impl SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + /// Returns the position of the element with the given key, or the position where it could be + /// inserted while maintaining the sort order. + pub fn binary_search_key(&self, key: &Q) -> Result + where + K: Borrow, + Q: Ord + ?Sized, + { + self.base + .binary_search_by(|elem| elem.key().borrow().cmp(key)) + } + + /// Return item index, if it exists in the set. + /// + /// Performs a binary search O(log n) over the elements to find the matching key. + pub fn get_index_of(&self, key: &Q) -> Option + where + K: Borrow, + Q: Ord + ?Sized, + { + self.binary_search_key(key).ok() + } + + /// Returns `true` if the set contains an element with the given key. + pub fn contains_key(&self, key: &Q) -> bool + where + K: Borrow, + Q: Ord + ?Sized, + { + self.binary_search_key(key).is_ok() + } + + /// Return a reference to the value stored for `key`, if it is present. + pub fn get(&self, key: &Q) -> Option<&V> + where + K: Borrow, + Q: Ord + ?Sized, + { + self.get_index_of(key).map(|index| &self.base[index]) + } + + /// Return item index and a reference to the value stored for `key`, if it is present. + pub fn get_full(&self, key: &Q) -> Option<(usize, &V)> + where + K: Borrow, + Q: Ord + ?Sized, + { + self.get_index_of(key) + .map(|index| (index, &self.base[index])) + } + + /// Return a mutable reference to the value stored for `key`, if it is present. + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where + K: Borrow, + Q: Ord + ?Sized, + { + self.get_index_of(key).map(|index| &mut self.base[index]) + } +} + +impl SortedKeyedVecSet { + /// Return a reference to the value stored at `index`, if it is present. + pub fn get_index(&self, index: usize) -> Option<&V> { + self.base.get(index) + } + + /// Return a mutable reference to the value stored at `index`, if it is present. + pub fn get_index_mut(&mut self, index: usize) -> Option<&mut V> { + self.base.get_mut(index) + } + + /// Get the first element. + pub fn first(&self) -> Option<&V> { + self.base.first() + } + + /// Get a mutable reference to the first element. + /// + /// The caller must not mutate the key portion of the element in a way that would invalidate + /// the sort order. + pub fn first_mut(&mut self) -> Option<&mut V> { + self.base.first_mut() + } + + /// Get the last element. + pub fn last(&self) -> Option<&V> { + self.base.last() + } + + /// Get a mutable reference to the last element. + /// + /// The caller must not mutate the key portion of the element in a way that would invalidate + /// the sort order. + pub fn last_mut(&mut self) -> Option<&mut V> { + self.base.last_mut() + } +} + +// Unchecked insertion (used by VacantEntry). +impl SortedKeyedVecSet { + /// Insert `value` at `index`, shifting subsequent elements to the right. + /// + /// # Safety + /// + /// The caller must ensure that inserting at `index` preserves the sort invariant: + /// `index <= len`, no existing element has the same key, and the inserted key sorts between + /// its neighbours. + pub unsafe fn insert_at_unchecked(&mut self, index: usize, value: V) { + self.base.insert(index, value); + } +} + +// Removal operations +impl SortedKeyedVecSet { + /// Removes the last (greatest-keyed) element from the set and returns it, or [`None`] if it + /// is empty. + pub fn pop_last(&mut self) -> Option { + self.base.pop() + } + + /// Removes the first (least-keyed) element from the set and returns it, or [`None`] if it is + /// empty. + pub fn pop_first(&mut self) -> Option { + if self.base.is_empty() { + None + } else { + Some(self.base.remove(0)) + } + } + + /// Removes and returns the element at position `index`, shifting all elements after it to + /// the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + pub fn remove_index(&mut self, index: usize) -> V { + self.base.remove(index) + } +} + +impl SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + /// Remove the element equivalent to `key` and return its value. + /// + /// The pair is removed by shifting all of the elements that follow it, preserving their + /// relative order (and therefore the sort invariant). + pub fn remove(&mut self, key: &Q) -> Option + where + K: Borrow, + Q: Ord + ?Sized, + { + self.get_index_of(key).map(|index| self.remove_index(index)) + } +} + +// Insertion operations +impl SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + /// Insert or replace an element, keeping the set sorted. + /// + /// If an equivalent key already exists: the key retains its position, its value is replaced + /// with `value`, and the old value is returned inside `Some(_)`. + /// + /// If no equivalent key existed: the value is inserted in its sorted position, and `None` is + /// returned. + pub fn insert(&mut self, value: V) -> Option { + self.insert_full(value).1 + } + + /// Insert or replace an element, returning its index. + /// + /// See [`Self::insert`] for semantics. + pub fn insert_full(&mut self, value: V) -> (usize, Option) { + match self.binary_search_key(value.key()) { + Ok(index) => { + let old = mem::replace(&mut self.base[index], value); + (index, Some(old)) + } + Err(index) => { + self.base.insert(index, value); + (index, None) + } + } + } + + /// Moves all elements from `other` into `self`, leaving `other` empty. + /// + /// If both sets contain an equivalent key, the value from `other` replaces the one in `self` + /// (matching `BTreeMap::append` semantics). + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel and building a fresh vector + /// with the merged contents. + pub fn append(&mut self, other: &mut SortedKeyedVecSet) { + if other.is_empty() { + return; + } + if self.is_empty() { + mem::swap(&mut self.base, &mut other.base); + return; + } + + let mut self_iter = mem::take(&mut self.base).into_iter(); + let mut other_iter = mem::take(&mut other.base).into_iter(); + let total = self_iter.len() + other_iter.len(); + let mut merged = Vec::with_capacity(total); + + let mut left = self_iter.next(); + let mut right = other_iter.next(); + loop { + match (left.take(), right.take()) { + (Some(l), Some(r)) => match l.key().cmp(r.key()) { + core::cmp::Ordering::Less => { + merged.push(l); + left = self_iter.next(); + right = Some(r); + } + core::cmp::Ordering::Greater => { + merged.push(r); + left = Some(l); + right = other_iter.next(); + } + core::cmp::Ordering::Equal => { + // Equal keys: `other` wins. + merged.push(r); + left = self_iter.next(); + right = other_iter.next(); + } + }, + (Some(l), None) => { + merged.push(l); + merged.extend(self_iter); + break; + } + (None, Some(r)) => { + merged.push(r); + merged.extend(other_iter); + break; + } + (None, None) => break, + } + } + + self.base = merged; + } +} + +// Range helpers +impl SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + /// Translate a key-bounded range into an index range over the backing slice. + pub(crate) fn key_range_to_indices(&self, range: R) -> (usize, usize) + where + K: Borrow, + Q: Ord + ?Sized, + R: RangeBounds, + { + let slice = self.base.as_slice(); + let start = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(key) => slice.partition_point(|elem| elem.key().borrow() < key), + Bound::Excluded(key) => slice.partition_point(|elem| elem.key().borrow() <= key), + }; + let end = match range.end_bound() { + Bound::Unbounded => slice.len(), + Bound::Included(key) => slice.partition_point(|elem| elem.key().borrow() <= key), + Bound::Excluded(key) => slice.partition_point(|elem| elem.key().borrow() < key), + }; + assert!(start <= end, "range start is greater than range end"); + (start, end) + } +} diff --git a/src/sorted_keyed/impls.rs b/src/sorted_keyed/impls.rs new file mode 100644 index 0000000..92e1416 --- /dev/null +++ b/src/sorted_keyed/impls.rs @@ -0,0 +1,262 @@ +use super::{Keyed, SortedKeyedVecSet}; +use alloc::vec::Vec; +use core::borrow::Borrow; +use core::ops::{Index, IndexMut}; + +impl Default for SortedKeyedVecSet { + fn default() -> Self { + SortedKeyedVecSet::new() + } +} + +impl Index<&Q> for SortedKeyedVecSet +where + V: Keyed, + K: Ord + Borrow, + Q: Ord + ?Sized, +{ + type Output = V; + + fn index(&self, key: &Q) -> &V { + self.get(key).expect("SortedKeyedVecSet: key not found") + } +} + +impl IndexMut<&Q> for SortedKeyedVecSet +where + V: Keyed, + K: Ord + Borrow, + Q: Ord + ?Sized, +{ + fn index_mut(&mut self, key: &Q) -> &mut V { + self.get_mut(key).expect("SortedKeyedVecSet: key not found") + } +} + +impl Index for SortedKeyedVecSet { + type Output = V; + + fn index(&self, index: usize) -> &Self::Output { + &self.base[index] + } +} + +impl IndexMut for SortedKeyedVecSet { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.base[index] + } +} + +impl Extend for SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + let iter = iterable.into_iter(); + let reserve = if self.is_empty() { + iter.size_hint().0 + } else { + let size_hint = iter.size_hint().0; + size_hint / 2 + size_hint % 2 + }; + self.reserve(reserve); + iter.for_each(move |value| { + self.insert(value); + }); + } +} + +impl<'a, K, V: Clone> Extend<&'a V> for SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.extend(iterable.into_iter().cloned()); + } +} + +impl FromIterator for SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + fn from_iter>(iter: I) -> Self { + let iter = iter.into_iter(); + let lower = iter.size_hint().0; + let mut set = SortedKeyedVecSet::with_capacity(lower); + set.extend(iter); + set + } +} + +impl From> for SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + /// Constructs a sorted set from a vector of values. + /// + /// When duplicate keys are present, the *last* occurrence wins (matching the behaviour of + /// inserting values one-by-one and of [`BTreeMap::from_iter`]). + /// + /// [`BTreeMap::from_iter`]: alloc::collections::BTreeMap::from_iter + fn from(mut vec: Vec) -> Self { + // Reverse + stable sort places the *last* occurrence of each key first within its run, so + // `dedup_by` keeps the latest value. + vec.reverse(); + vec.sort_by(|a, b| a.key().cmp(b.key())); + vec.dedup_by(|a, b| Keyed::key(&*a).cmp(Keyed::key(&*b)).is_eq()); + // SAFETY: the vector is now sorted by key with no duplicates. + unsafe { Self::from_vec_unchecked(vec) } + } +} + +impl From<&[V]> for SortedKeyedVecSet +where + V: Clone + Keyed, + K: Ord, +{ + fn from(slice: &[V]) -> Self { + slice.iter().cloned().collect() + } +} + +impl From<&mut [V]> for SortedKeyedVecSet +where + V: Clone + Keyed, + K: Ord, +{ + fn from(slice: &mut [V]) -> Self { + slice.iter().cloned().collect() + } +} + +impl From<[V; N]> for SortedKeyedVecSet +where + V: Keyed, + K: Ord, +{ + fn from(arr: [V; N]) -> Self { + SortedKeyedVecSet::from_iter(arr) + } +} + +impl PartialEq for SortedKeyedVecSet +where + V: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + // Both sides are sorted by key with no duplicates, so a slice-wise comparison suffices. + self.base == other.base + } +} + +impl Eq for SortedKeyedVecSet where V: Eq {} + +#[cfg(test)] +mod test { + use super::*; + extern crate alloc; + use alloc::vec; + + #[derive(Debug, PartialEq, Eq, Clone)] + struct Entry(i32, &'static str); + + impl Keyed for Entry { + fn key(&self) -> &i32 { + &self.0 + } + } + + #[test] + fn default() { + let set: SortedKeyedVecSet = SortedKeyedVecSet::default(); + assert_eq!(set.len(), 0); + } + + #[test] + fn index_by_key() { + let mut set = SortedKeyedVecSet::::new(); + set.insert(Entry(1, "a")); + assert_eq!(set[&1], Entry(1, "a")); + } + + #[test] + fn extend_and_sort() { + let mut set = SortedKeyedVecSet::::new(); + set.extend(vec![Entry(3, "c"), Entry(1, "a"), Entry(2, "b")]); + assert_eq!(set.len(), 3); + assert_eq!(set.as_slice()[0], Entry(1, "a")); + assert_eq!(set.as_slice()[1], Entry(2, "b")); + assert_eq!(set.as_slice()[2], Entry(3, "c")); + } + + #[test] + fn from_vec_dedup_keeps_last() { + let set = SortedKeyedVecSet::::from(vec![ + Entry(2, "b"), + Entry(1, "a"), + Entry(2, "b2"), + ]); + assert_eq!(set.len(), 2); + assert_eq!(set[&1], Entry(1, "a")); + // Duplicate key (2) kept the last-seen value, matching `insert` semantics. + assert_eq!(set[&2], Entry(2, "b2")); + } + + #[test] + fn remove_preserves_order() { + let mut set = SortedKeyedVecSet::::new(); + set.insert(Entry(1, "a")); + set.insert(Entry(2, "b")); + set.insert(Entry(3, "c")); + assert_eq!(set.remove(&2), Some(Entry(2, "b"))); + assert_eq!(set.as_slice()[0], Entry(1, "a")); + assert_eq!(set.as_slice()[1], Entry(3, "c")); + } + + #[test] + fn pop_first_and_last() { + let mut set = SortedKeyedVecSet::::new(); + set.insert(Entry(2, "b")); + set.insert(Entry(1, "a")); + set.insert(Entry(3, "c")); + assert_eq!(set.pop_first(), Some(Entry(1, "a"))); + assert_eq!(set.pop_last(), Some(Entry(3, "c"))); + assert_eq!(set.pop_first(), Some(Entry(2, "b"))); + assert_eq!(set.pop_first(), None); + } + + #[test] + fn key_range() { + let set = SortedKeyedVecSet::::from(vec![ + Entry(1, "a"), + Entry(3, "c"), + Entry(5, "e"), + Entry(7, "g"), + ]); + assert_eq!(set.key_range_to_indices::(2..6), (1, 3)); + assert_eq!(set.key_range_to_indices::(..), (0, 4)); + assert_eq!(set.key_range_to_indices::(3..=5), (1, 3)); + } + + #[test] + fn eq() { + assert_eq!( + SortedKeyedVecSet::::from(vec![Entry(1, "a"), Entry(2, "b")]), + SortedKeyedVecSet::::from(vec![Entry(2, "b"), Entry(1, "a")]) + ); + assert_ne!( + SortedKeyedVecSet::::from(vec![Entry(1, "a")]), + SortedKeyedVecSet::::from(vec![]) + ); + } +} diff --git a/src/sorted_map.rs b/src/sorted_map.rs new file mode 100644 index 0000000..76bd1fe --- /dev/null +++ b/src/sorted_map.rs @@ -0,0 +1,1024 @@ +//! `SortedVecMap` is a vector-based map implementation which keeps its entries sorted by key. + +mod entry; +mod impls; +mod iter; +#[cfg(feature = "serde")] +mod serde; + +use super::{Entries, Slot, TryReserveError, sorted_keyed::SortedKeyedVecSet}; +use alloc::vec::Vec; +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::ops::RangeBounds; +use core::ptr; + +pub use self::entry::{Entry, OccupiedEntry, VacantEntry}; +pub use self::iter::*; + +/// A vector-based map implementation which keeps its entries sorted by key. +/// +/// Internally it is represented as a `Vec<(K, V)>` whose entries are always kept sorted by the +/// key. Iteration order matches the sort order of the keys. +/// +/// # Complexity +/// +/// | operation | cost | +/// |--------------------------------------------|-------------------| +/// | `get` / `contains_key` / `binary_search_*` | *O*(log *n*) | +/// | `insert` / `remove` / `pop_first` | *O*(*n*) (shift) | +/// | `pop_last` | *O*(1) | +/// | `append` | *O*(*n* + *m*) | +/// | `iter` / `range` | *O*(*k*) | +/// +/// Lookups are faster than [`VecMap`](crate::VecMap)'s linear scan, but writes pay a shift cost +/// that [`BTreeMap`](alloc::collections::BTreeMap) avoids. Prefer `SortedVecMap` for read-heavy +/// workloads with small-to-moderate *n* or when the contiguous memory layout matters. +/// +/// Unlike [`VecMap`](crate::VecMap), `SortedVecMap` requires keys to implement [`Ord`], and +/// operations that would disturb the sort order (such as `insert_at`, `reverse`, `sort_keys`, +/// etc.) are intentionally not provided. +#[derive(Clone, Debug)] +pub struct SortedVecMap { + base: SortedKeyedVecSet>, +} + +impl SortedVecMap { + /// Create a new map. (Does not allocate.) + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = SortedVecMap::new(); + /// ``` + pub const fn new() -> Self { + SortedVecMap { + base: SortedKeyedVecSet::new(), + } + } + + /// Create a new map with capacity for `capacity` key-value pairs. (Does not allocate if + /// `capacity` is zero.) + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = SortedVecMap::with_capacity(10); + /// assert_eq!(map.len(), 0); + /// assert!(map.capacity() >= 10); + /// ``` + pub fn with_capacity(capacity: usize) -> Self { + SortedVecMap { + base: SortedKeyedVecSet::with_capacity(capacity), + } + } + + /// Returns the number of entries the map can hold without reallocating. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = SortedVecMap::with_capacity(10); + /// assert_eq!(map.capacity(), 10); + /// ``` + pub fn capacity(&self) -> usize { + self.base.capacity() + } + + /// Returns the number of entries in the map, also referred to as its 'length'. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut a = SortedVecMap::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1, "a"); + /// assert_eq!(a.len(), 1); + /// ``` + pub fn len(&self) -> usize { + self.base.len() + } + + /// Returns `true` if the map contains no entries. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut a = SortedVecMap::new(); + /// assert!(a.is_empty()); + /// a.insert(1, "a"); + /// assert!(!a.is_empty()); + /// ``` + pub fn is_empty(&self) -> bool { + self.base.is_empty() + } + + /// Clears the map, removing all entries. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut a = SortedVecMap::new(); + /// a.insert(1, "a"); + /// a.clear(); + /// assert!(a.is_empty()); + /// ``` + pub fn clear(&mut self) { + self.base.clear(); + } + + /// Shortens the map, keeping the first `len` key-value pairs (in sort order) and dropping the + /// rest. + /// + /// If `len` is greater than the map's current length, this has no effect. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from([("a", 1), ("b", 2), ("c", 3), ("d", 4)]); + /// map.truncate(2); + /// assert_eq!(map, SortedVecMap::from([("a", 1), ("b", 2)])); + /// ``` + pub fn truncate(&mut self, len: usize) { + self.base.truncate(len); + } + + /// Reserves capacity for at least `additional` more elements to be inserted in the given + /// `SortedVecMap`. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("a", 1)]); + /// map.reserve(10); + /// assert!(map.capacity() >= 11); + /// ``` + pub fn reserve(&mut self, additional: usize) { + self.base.reserve(additional); + } + + /// Reserves the minimum capacity for at least `additional` more elements to be inserted in + /// the given `SortedVecMap`. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("a", 1)]); + /// map.reserve_exact(10); + /// assert!(map.capacity() >= 11); + /// ``` + pub fn reserve_exact(&mut self, additional: usize) { + self.base.reserve_exact(additional); + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + /// + /// # Examples + /// + /// ``` + /// use vecmap::{SortedVecMap, TryReserveError}; + /// + /// fn process(data: &[(u32, u32)]) -> Result, TryReserveError> { + /// let mut output = SortedVecMap::new(); + /// output.try_reserve(data.len())?; + /// output.extend(data.iter().copied()); + /// Ok(output) + /// } + /// # process(&[(1, 1), (2, 2)]).expect("should reserve"); + /// ``` + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` more elements to be + /// inserted. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + /// + /// # Examples + /// + /// ``` + /// use vecmap::{SortedVecMap, TryReserveError}; + /// + /// fn process(data: &[(u32, u32)]) -> Result, TryReserveError> { + /// let mut output = SortedVecMap::new(); + /// output.try_reserve_exact(data.len())?; + /// output.extend(data.iter().copied()); + /// Ok(output) + /// } + /// # process(&[(1, 1), (2, 2)]).expect("should reserve"); + /// ``` + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve_exact(additional) + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`. The + /// sort order is preserved. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = (0..8).map(|x| (x, x * 10)).collect(); + /// map.retain(|&k, _| k % 2 == 0); + /// assert_eq!(map.len(), 4); + /// ``` + pub fn retain(&mut self, mut f: F) + where + F: FnMut(&K, &mut V) -> bool, + { + self.base.retain_mut(|slot| { + let (key, value) = slot.ref_mut(); + f(key, value) + }); + } + + /// Shrinks the capacity of the map as much as possible. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = SortedVecMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// assert!(map.capacity() >= 100); + /// map.shrink_to_fit(); + /// assert!(map.capacity() >= 2); + /// ``` + pub fn shrink_to_fit(&mut self) { + self.base.shrink_to_fit(); + } + + /// Shrinks the capacity of the map with a lower limit. + /// + /// If the current capacity is less than the lower limit, this is a no-op. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap = SortedVecMap::with_capacity(100); + /// map.insert(1, 2); + /// map.insert(3, 4); + /// map.shrink_to(10); + /// assert!(map.capacity() >= 10); + /// ``` + pub fn shrink_to(&mut self, min_capacity: usize) { + self.base.shrink_to(min_capacity); + } + + /// Splits the map into two at the given index. + /// + /// Returns a newly allocated map containing the key-value pairs in the range `[at, len)`. + /// After the call, the original map will be left containing the key-value pairs `[0, at)` + /// with its previous capacity unchanged. Both halves remain sorted. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from([("a", 1), ("b", 2), ("c", 3)]); + /// let map2 = map.split_off(1); + /// assert_eq!(map, SortedVecMap::from([("a", 1)])); + /// assert_eq!(map2, SortedVecMap::from([("b", 2), ("c", 3)])); + /// ``` + pub fn split_off(&mut self, at: usize) -> SortedVecMap { + SortedVecMap { + base: self.base.split_off(at), + } + } + + /// Search over the map for a key. + /// + /// Returns the position where that key is present, or the position where it can be inserted + /// to maintain the sort. See [`slice::binary_search`] for more details. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("a", 1), ("b", 2), ("d", 4)]); + /// assert_eq!(map.binary_search_keys(&"b"), Ok(1)); + /// assert_eq!(map.binary_search_keys(&"c"), Err(2)); + /// assert_eq!(map.binary_search_keys(&"z"), Err(3)); + /// ``` + pub fn binary_search_keys(&self, key: &K) -> Result + where + K: Ord, + { + self.binary_search_by(|k, _| k.cmp(key)) + } + + /// Search over the map with a comparator function. + /// + /// Returns the position where that value is present, or the position where it can be + /// inserted to maintain the sort. See [`slice::binary_search_by`] for more details. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("a", 1), ("b", 2), ("d", 4)]); + /// assert_eq!(map.binary_search_by(|k, _| k.cmp(&"b")), Ok(1)); + /// assert_eq!(map.binary_search_by(|k, _| k.cmp(&"c")), Err(2)); + /// ``` + pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result + where + F: FnMut(&'a K, &'a V) -> Ordering, + { + self.as_slice().binary_search_by(|(k, v)| f(k, v)) + } + + /// Search over the map with an extraction function. + /// + /// Returns the position where that value is present, or the position where it can be + /// inserted to maintain the sort. See [`slice::binary_search_by_key`] for more details. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("a", 1), ("b", 2), ("d", 4)]); + /// assert_eq!(map.binary_search_by_key(&"b", |&k, _| k), Ok(1)); + /// assert_eq!(map.binary_search_by_key(&"c", |&k, _| k), Err(2)); + /// assert_eq!(map.binary_search_by_key(&4, |_, &v| v), Ok(2)); + /// ``` + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result + where + F: FnMut(&'a K, &'a V) -> B, + B: Ord, + { + self.as_slice().binary_search_by_key(b, |(k, v)| f(k, v)) + } + + /// Returns the index of the partition point according to the given predicate (the index of + /// the first element of the second partition). + /// + /// See [`slice::partition_point`] for more details. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("a", 1), ("b", 2), ("d", 4)]); + /// assert_eq!(map.partition_point(|&k, _| k < "d"), 2); + /// assert_eq!(map.partition_point(|_, &v| v < 2), 1); + /// ``` + pub fn partition_point

(&self, mut pred: P) -> usize + where + P: FnMut(&K, &V) -> bool, + { + self.as_slice().partition_point(|(k, v)| pred(k, v)) + } + + /// Removes the specified range from the vector in bulk, returning all removed elements as an + /// iterator. + /// + /// The returned iterator keeps a mutable borrow on the vector to optimize its implementation. + /// The range is interpreted in index space, not key space. + /// + /// # Panics + /// + /// Panics if the starting point is greater than the end point or if the end point is greater + /// than the length of the vector. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut v = SortedVecMap::from([("a", 1), ("b", 2), ("c", 3)]); + /// let u: SortedVecMap<_, _> = v.drain(1..).collect(); + /// assert_eq!(v, SortedVecMap::from([("a", 1)])); + /// assert_eq!(u, SortedVecMap::from([("b", 2), ("c", 3)])); + /// ``` + pub fn drain(&mut self, range: R) -> Drain<'_, K, V> + where + R: RangeBounds, + { + Drain::new(self, range) + } + + /// Extracts a slice containing the map entries in sort order. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("b", 2), ("a", 1), ("c", 3)]); + /// let slice = map.as_slice(); + /// assert_eq!(slice, [("a", 1), ("b", 2), ("c", 3)]); + /// ``` + pub fn as_slice(&self) -> &[(K, V)] { + // SAFETY: `&[Slot]` and `&[(K, V)]` have the same memory layout. + unsafe { &*(ptr::from_ref::<[Slot]>(self.base.as_slice()) as *const [(K, V)]) } + } + + /// Copies the map entries into a new `Vec<(K, V)>` in sort order. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("b", 2), ("a", 1), ("c", 3)]); + /// let vec = map.to_vec(); + /// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]); + /// ``` + pub fn to_vec(&self) -> Vec<(K, V)> + where + K: Clone, + V: Clone, + { + self.iter().map(|(k, v)| (k.clone(), v.clone())).collect() + } + + /// Takes ownership of the map and returns its entries as a `Vec<(K, V)>` in sort order. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from([("b", 2), ("a", 1), ("c", 3)]); + /// let vec = map.into_vec(); + /// assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]); + /// ``` + pub fn into_vec(self) -> Vec<(K, V)> { + // SAFETY: `Vec>` and `Vec<(K, V)>` have the same memory layout. + unsafe { super::transmute_vec(self.base.into_vec()) } + } + + /// Takes ownership of the provided vector and converts it into `SortedVecMap`. + /// + /// # Safety + /// + /// The vector must be sorted strictly by key (no duplicate keys). One way to guarantee this + /// is to sort the vector (e.g. by using [`[T]::sort_by_key`][slice-sort-by-key]) and then + /// drop duplicate keys (e.g. by using [`Vec::dedup_by_key`]). + /// + /// [slice-sort-by-key]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_key + /// + /// # Example + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut vec = vec![("b", 2), ("a", 1), ("c", 3), ("b", 4)]; + /// vec.sort_by_key(|slot| slot.0); + /// vec.dedup_by_key(|slot| slot.0); + /// // SAFETY: we've just sorted and deduplicated the vector. + /// let map = unsafe { SortedVecMap::from_vec_unchecked(vec) }; + /// + /// assert_eq!(map, SortedVecMap::from([("a", 1), ("b", 2), ("c", 3)])); + /// ``` + pub unsafe fn from_vec_unchecked(vec: Vec<(K, V)>) -> Self { + // SAFETY: `Vec<(K, V)>` and `Vec>` have the same memory layout. + let base_vec = unsafe { super::transmute_vec(vec) }; + SortedVecMap { + base: unsafe { SortedKeyedVecSet::from_vec_unchecked(base_vec) }, + } + } +} + +// Lookup operations. +impl SortedVecMap { + /// Return `true` if an equivalent to `key` exists in the map. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.contains_key(&1), true); + /// assert_eq!(map.contains_key(&2), false); + /// ``` + pub fn contains_key(&self, key: &Q) -> bool + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.contains_key(key) + } + + /// Get the first (least-keyed) key-value pair. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// assert_eq!(map.first_key_value(), Some((&"a", &1))); + /// ``` + pub fn first_key_value(&self) -> Option<(&K, &V)> { + self.base.first().map(Slot::refs) + } + + /// Get the last (greatest-keyed) key-value pair. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// assert_eq!(map.last_key_value(), Some((&"b", &2))); + /// ``` + pub fn last_key_value(&self) -> Option<(&K, &V)> { + self.base.last().map(Slot::refs) + } + + /// Get the first (least-keyed) key-value pair, with a mutable reference to the value. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// if let Some((_, v)) = map.first_key_value_mut() { + /// *v = 10; + /// } + /// assert_eq!(map[&"a"], 10); + /// ``` + pub fn first_key_value_mut(&mut self) -> Option<(&K, &mut V)> { + self.base.first_mut().map(Slot::ref_mut) + } + + /// Get the last (greatest-keyed) key-value pair, with a mutable reference to the value. + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// if let Some((_, v)) = map.last_key_value_mut() { + /// *v = 20; + /// } + /// assert_eq!(map[&"b"], 20); + /// ``` + pub fn last_key_value_mut(&mut self) -> Option<(&K, &mut V)> { + self.base.last_mut().map(Slot::ref_mut) + } + + /// Return a reference to the value stored for `key`, if it is present. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::new(); + /// map.insert(1, "a"); + /// assert_eq!(map.get(&1), Some(&"a")); + /// assert_eq!(map.get(&2), None); + /// ``` + pub fn get(&self, key: &Q) -> Option<&V> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get(key).map(Slot::value) + } + + /// Return a mutable reference to the value stored for `key`, if it is present. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::new(); + /// map.insert(1, "a"); + /// if let Some(x) = map.get_mut(&1) { + /// *x = "b"; + /// } + /// assert_eq!(map[&1], "b"); + /// ``` + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get_mut(key).map(Slot::value_mut) + } + + /// Return references to the key-value pair stored at `index`, if it is present. + /// + /// The index is an index into the sort-ordered sequence of entries. + pub fn get_index(&self, index: usize) -> Option<(&K, &V)> { + self.base.get_index(index).map(Slot::refs) + } + + /// Return a reference to the key and a mutable reference to the value stored at `index`, if + /// it is present. + pub fn get_index_mut(&mut self, index: usize) -> Option<(&K, &mut V)> { + self.base.get_index_mut(index).map(Slot::ref_mut) + } + + /// Return the index and references to the key-value pair stored for `key`, if it is present. + pub fn get_full(&self, key: &Q) -> Option<(usize, &K, &V)> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base + .get_full(key) + .map(|(index, slot)| (index, slot.key(), slot.value())) + } + + /// Return the index, a reference to the key and a mutable reference to the value stored for + /// `key`, if it is present. + pub fn get_full_mut(&mut self, key: &Q) -> Option<(usize, &K, &mut V)> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get_index_of(key).map(|index| { + let (key, value) = self.base[index].ref_mut(); + (index, key, value) + }) + } + + /// Return references to the key-value pair stored for `key`, if it is present. + pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get(key).map(Slot::refs) + } + + /// Return the item index, if it exists in the map. + pub fn get_index_of(&self, key: &Q) -> Option + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get_index_of(key) + } +} + +// Removal operations. +impl SortedVecMap { + /// Removes the first (least-keyed) element from the map and returns it, or [`None`] if the + /// map is empty. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// assert_eq!(map.pop_first(), Some(("a", 1))); + /// assert_eq!(map.pop_first(), Some(("b", 2))); + /// assert_eq!(map.pop_first(), None); + /// ``` + pub fn pop_first(&mut self) -> Option<(K, V)> { + self.base.pop_first().map(Slot::into_key_value) + } + + /// Removes the last (greatest-keyed) element from the map and returns it, or [`None`] if the + /// map is empty. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([("b", 2), ("a", 1)]); + /// assert_eq!(map.pop_last(), Some(("b", 2))); + /// assert_eq!(map.pop_last(), Some(("a", 1))); + /// assert_eq!(map.pop_last(), None); + /// ``` + pub fn pop_last(&mut self) -> Option<(K, V)> { + self.base.pop_last().map(Slot::into_key_value) + } + + /// Remove the key-value pair equivalent to `key` and return its value. + /// + /// The pair is removed by shifting all of the elements that follow it, preserving their + /// relative order (and therefore the sort invariant). + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([(1, "a"), (2, "b"), (3, "c"), (4, "d")]); + /// assert_eq!(map.remove(&2), Some("b")); + /// assert_eq!(map.remove(&2), None); + /// ``` + pub fn remove(&mut self, key: &Q) -> Option + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.remove(key).map(Slot::into_value) + } + + /// Remove and return the key-value pair equivalent to `key`. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::from_iter([(1, "a"), (2, "b"), (3, "c")]); + /// assert_eq!(map.remove_entry(&2), Some((2, "b"))); + /// assert_eq!(map.remove_entry(&2), None); + /// ``` + pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> + where + K: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.remove(key).map(Slot::into_key_value) + } + + /// Removes and returns the key-value pair at position `index` within the map, shifting all + /// elements after it to the left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut v = SortedVecMap::from([("a", 1), ("b", 2), ("c", 3)]); + /// assert_eq!(v.remove_index(1), ("b", 2)); + /// assert_eq!(v, SortedVecMap::from([("a", 1), ("c", 3)])); + /// ``` + pub fn remove_index(&mut self, index: usize) -> (K, V) { + self.base.remove_index(index).into_key_value() + } +} + +// Insertion operations. +impl SortedVecMap +where + K: Ord, +{ + /// Insert a key-value pair in the map. + /// + /// If an equivalent key already exists in the map: the key remains at its sorted position, + /// its corresponding value is updated with `value`, and the old value is returned inside + /// `Some(_)`. + /// + /// If no equivalent key existed: the new key-value pair is inserted at the correct sorted + /// position, and `None` is returned. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::new(); + /// assert_eq!(map.insert(37, "a"), None); + /// assert_eq!(map.is_empty(), false); + /// + /// map.insert(37, "b"); + /// assert_eq!(map.insert(37, "c"), Some("b")); + /// assert_eq!(map[&37], "c"); + /// ``` + pub fn insert(&mut self, key: K, value: V) -> Option { + self.insert_full(key, value).1 + } + + /// Insert a key-value pair in the map, and get its (sorted) index. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map = SortedVecMap::new(); + /// assert_eq!(map.insert_full("b", 2), (0, None)); + /// assert_eq!(map.insert_full("a", 1), (0, None)); + /// // "a" sorts before "b", so inserting "b" again reports index 1. + /// assert_eq!(map.insert_full("b", 3), (1, Some(2))); + /// ``` + pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option) { + let (index, old_slot) = self.base.insert_full(Slot::new(key, value)); + (index, old_slot.map(Slot::into_value)) + } + + /// Get the given key's corresponding entry in the map for insertion and/or in-place + /// manipulation. + /// + /// ## Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut letters = SortedVecMap::new(); + /// + /// for ch in "a short treatise on fungi".chars() { + /// letters.entry(ch).and_modify(|c| *c += 1).or_insert(1); + /// } + /// + /// assert_eq!(letters[&'s'], 2); + /// assert_eq!(letters[&'t'], 3); + /// assert_eq!(letters[&'u'], 1); + /// assert_eq!(letters.get(&'y'), None); + /// ``` + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { + match self.base.binary_search_key(&key) { + Ok(index) => Entry::Occupied(OccupiedEntry::new(self, key, index)), + Err(index) => Entry::Vacant(VacantEntry::new(self, key, index)), + } + } + + /// Moves all key-value pairs from `other` into `self`, leaving `other` empty. + /// + /// When a key exists in both maps, the value from `other` overwrites the one in `self`, + /// matching [`BTreeMap::append`](alloc::collections::BTreeMap::append) semantics. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut a = SortedVecMap::from([(3, "c"), (2, "b"), (1, "a")]); + /// let mut b = SortedVecMap::from([(3, "d"), (4, "e"), (5, "f")]); + /// + /// a.append(&mut b); + /// + /// assert_eq!(a.len(), 5); + /// assert_eq!(b.len(), 0); + /// + /// assert_eq!(a[&3], "d"); // "c" was overwritten by "d" from `b`. + /// ``` + pub fn append(&mut self, other: &mut SortedVecMap) { + self.base.append(&mut other.base); + } +} + +// Range iterators. +impl SortedVecMap +where + K: Ord, +{ + /// Constructs an iterator over a sub-range of entries in the map. + /// + /// The simplest way is to use the range syntax `min..max`, thus `range(min..max)` will yield + /// elements from `min` (inclusive) to `max` (exclusive). The range may also be specified as + /// `(Bound<&K>, Bound<&K>)`, so for example `range((Excluded(&4), Included(&10)))` will yield + /// a left-exclusive, right-inclusive range from 4 to 10. + /// + /// # Panics + /// + /// Panics if the range's start is greater than its end. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let map: SortedVecMap<_, _> = [(3, "a"), (5, "b"), (8, "c")].into_iter().collect(); + /// let collected: Vec<_> = map.range(4..9).map(|(k, v)| (*k, *v)).collect(); + /// assert_eq!(collected, vec![(5, "b"), (8, "c")]); + /// ``` + pub fn range(&self, range: R) -> Range<'_, K, V> + where + K: Borrow, + Q: Ord + ?Sized, + R: RangeBounds, + { + let (start, end) = self.base.key_range_to_indices(range); + Range::new(&self.base.as_slice()[start..end]) + } + + /// Constructs a mutable iterator over a sub-range of entries in the map. + /// + /// See [`range`](SortedVecMap::range) for range-specification details. + /// + /// # Panics + /// + /// Panics if the range's start is greater than its end. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap<_, _> = [(3, 1), (5, 1), (8, 1)].into_iter().collect(); + /// for (_, v) in map.range_mut(4..9) { + /// *v += 10; + /// } + /// assert_eq!(map[&3], 1); + /// assert_eq!(map[&5], 11); + /// assert_eq!(map[&8], 11); + /// ``` + pub fn range_mut(&mut self, range: R) -> RangeMut<'_, K, V> + where + K: Borrow, + Q: Ord + ?Sized, + R: RangeBounds, + { + let (start, end) = self.base.key_range_to_indices(range); + RangeMut::new(&mut self.base.as_mut_slice()[start..end]) + } +} + +// Iterator adapters. +impl SortedVecMap { + /// An iterator visiting all key-value pairs in sort order. The iterator element type is + /// `(&'a K, &'a V)`. + pub fn iter(&self) -> Iter<'_, K, V> { + Iter::new(self.as_entries()) + } + + /// An iterator visiting all key-value pairs in sort order, with mutable references to the + /// values. The iterator element type is `(&'a K, &'a mut V)`. + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + IterMut::new(self.as_entries_mut()) + } + + /// An iterator visiting all keys in sort order. The iterator element type is `&'a K`. + pub fn keys(&self) -> Keys<'_, K, V> { + Keys::new(self.as_entries()) + } + + /// Creates a consuming iterator visiting all the keys in sort order. The object cannot be + /// used after calling this. The iterator element type is `K`. + pub fn into_keys(self) -> IntoKeys { + IntoKeys::new(self.into_entries()) + } + + /// An iterator visiting all values in sort order. The iterator element type is `&'a V`. + pub fn values(&self) -> Values<'_, K, V> { + Values::new(self.as_entries()) + } + + /// An iterator visiting all values mutably in sort order. The iterator element type is + /// `&'a mut V`. + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + ValuesMut::new(self.as_entries_mut()) + } + + /// Creates a consuming iterator visiting all the values in sort order. The object cannot be + /// used after calling this. The iterator element type is `V`. + pub fn into_values(self) -> IntoValues { + IntoValues::new(self.into_entries()) + } +} + +impl Entries for SortedVecMap { + type Entry = Slot; + + fn as_entries(&self) -> &[Self::Entry] { + self.base.as_slice() + } + + fn as_entries_mut(&mut self) -> &mut [Self::Entry] { + self.base.as_mut_slice() + } + + fn into_entries(self) -> Vec { + self.base.into_vec() + } +} diff --git a/src/sorted_map/entry.rs b/src/sorted_map/entry.rs new file mode 100644 index 0000000..6a721a7 --- /dev/null +++ b/src/sorted_map/entry.rs @@ -0,0 +1,228 @@ +use super::SortedVecMap; +use crate::Slot; +use core::mem; + +/// Entry for an existing key-value pair or a vacant slot in a [`SortedVecMap`]. +#[derive(Debug)] +pub enum Entry<'a, K, V> { + /// Existing slot with equivalent key. + Occupied(OccupiedEntry<'a, K, V>), + /// Vacant slot (no equivalent key in the map). + Vacant(VacantEntry<'a, K, V>), +} + +impl<'a, K, V> Entry<'a, K, V> +where + K: Ord, +{ + /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable + /// reference to the value in the entry. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecMap; + /// + /// let mut map: SortedVecMap<&str, u32> = SortedVecMap::new(); + /// + /// map.entry("poneyland").or_insert(3); + /// assert_eq!(map["poneyland"], 3); + /// + /// *map.entry("poneyland").or_insert(10) *= 2; + /// assert_eq!(map["poneyland"], 6); + /// ``` + pub fn or_insert(self, default: V) -> &'a mut V { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(default), + } + } + + /// Ensures a value is in the entry by inserting the result of the default function if empty, + /// and returns a mutable reference to the value in the entry. + pub fn or_insert_with(self, call: F) -> &'a mut V + where + F: FnOnce() -> V, + { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(call()), + } + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default + /// function. The default function receives a reference to the key that was moved during the + /// `.entry(key)` call so callers can compute a value from the key without cloning. + pub fn or_insert_with_key(self, default: F) -> &'a mut V + where + F: FnOnce(&K) -> V, + { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => { + let value = default(&entry.key); + entry.insert(value) + } + } + } + + /// Returns a reference to this entry's key. + pub fn key(&self) -> &K { + match self { + Entry::Occupied(entry) => entry.key(), + Entry::Vacant(entry) => entry.key(), + } + } + + /// Returns the index where the key-value pair exists or will be inserted. + pub fn index(&self) -> usize { + match self { + Entry::Occupied(entry) => entry.index(), + Entry::Vacant(entry) => entry.index(), + } + } + + /// Provides in-place mutable access to an occupied entry before any potential inserts into + /// the map. + pub fn and_modify(self, f: F) -> Self + where + F: FnOnce(&mut V), + { + match self { + Entry::Occupied(mut o) => { + f(o.get_mut()); + Entry::Occupied(o) + } + x => x, + } + } + + /// Ensures a value is in the entry by inserting the default value if empty, and returns a + /// mutable reference to the value in the entry. + pub fn or_default(self) -> &'a mut V + where + V: Default, + { + match self { + Entry::Occupied(entry) => entry.into_mut(), + Entry::Vacant(entry) => entry.insert(V::default()), + } + } +} + +/// A view into an occupied entry in a [`SortedVecMap`]. It is part of the [`Entry`] enum. +#[derive(Debug)] +pub struct OccupiedEntry<'a, K, V> { + map: &'a mut SortedVecMap, + key: K, + index: usize, +} + +impl<'a, K, V> OccupiedEntry<'a, K, V> { + pub(super) fn new( + map: &'a mut SortedVecMap, + key: K, + index: usize, + ) -> OccupiedEntry<'a, K, V> { + OccupiedEntry { map, key, index } + } + + /// Gets a reference to the key in the entry. + pub fn key(&self) -> &K { + &self.key + } + + /// Gets the index of the entry within the sorted sequence. + pub fn index(&self) -> usize { + self.index + } + + /// Take ownership of the key. + pub fn into_key(self) -> K { + self.key + } + + /// Gets a reference to the value in the entry. + pub fn get(&self) -> &V { + &self.map[self.index] + } + + /// Gets a mutable reference to the value in the entry. + pub fn get_mut(&mut self) -> &mut V { + &mut self.map[self.index] + } + + /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry with a + /// lifetime bound to the map itself. + pub fn into_mut(self) -> &'a mut V { + &mut self.map[self.index] + } + + /// Sets the value of the entry, and returns the entry's old value. + pub fn insert(&mut self, value: V) -> V { + mem::replace(self.get_mut(), value) + } + + /// Removes and returns the key-value pair stored in the map for this entry. + /// + /// Like `Vec::remove`, the pair is removed by shifting all of the elements that follow it, + /// preserving their relative order (and therefore the sort invariant). + pub fn remove_entry(self) -> (K, V) { + self.map.remove_index(self.index) + } + + /// Removes the key-value pair stored in the map for this entry, and returns the value. + pub fn remove(self) -> V { + self.remove_entry().1 + } +} + +/// A view into a vacant entry in a [`SortedVecMap`]. It is part of the [`Entry`] enum. +/// +/// The vacant entry stores the insertion index (the `Err` result of the failed binary search) +/// so that inserting into it is a single shift of at most *n* elements, without a second search. +#[derive(Debug)] +pub struct VacantEntry<'a, K, V> { + map: &'a mut SortedVecMap, + key: K, + index: usize, +} + +impl<'a, K, V> VacantEntry<'a, K, V> { + pub(super) fn new( + map: &'a mut SortedVecMap, + key: K, + index: usize, + ) -> VacantEntry<'a, K, V> { + VacantEntry { map, key, index } + } + + /// Gets a reference to the key that would be used when inserting a value through the + /// `VacantEntry`. + pub fn key(&self) -> &K { + &self.key + } + + /// Returns the index at which the key-value pair will be inserted. + pub fn index(&self) -> usize { + self.index + } + + /// Take ownership of the key. + pub fn into_key(self) -> K { + self.key + } + + /// Sets the value of the entry with the `VacantEntry`'s key, and returns a mutable reference + /// to it. + pub fn insert(self, value: V) -> &'a mut V { + // SAFETY: the binary search that produced `self.index` guaranteed the slot is vacant and + // that inserting at this position preserves the sort order. + unsafe { + self.map + .base + .insert_at_unchecked(self.index, Slot::new(self.key, value)); + } + &mut self.map[self.index] + } +} diff --git a/src/sorted_map/impls.rs b/src/sorted_map/impls.rs new file mode 100644 index 0000000..5fd3c65 --- /dev/null +++ b/src/sorted_map/impls.rs @@ -0,0 +1,397 @@ +use super::SortedVecMap; +use alloc::vec::Vec; +use core::borrow::Borrow; +use core::ops::{Index, IndexMut}; + +impl Default for SortedVecMap { + fn default() -> Self { + SortedVecMap::new() + } +} + +impl Index<&Q> for SortedVecMap +where + K: Ord + Borrow, + Q: Ord + ?Sized, +{ + type Output = V; + + fn index(&self, key: &Q) -> &V { + self.get(key).expect("SortedVecMap: key not found") + } +} + +impl IndexMut<&Q> for SortedVecMap +where + K: Ord + Borrow, + Q: Ord + ?Sized, +{ + fn index_mut(&mut self, key: &Q) -> &mut V { + self.get_mut(key).expect("SortedVecMap: key not found") + } +} + +impl Index for SortedVecMap { + type Output = V; + + fn index(&self, index: usize) -> &V { + self.get_index(index) + .expect("SortedVecMap: index out of bounds") + .1 + } +} + +impl IndexMut for SortedVecMap { + fn index_mut(&mut self, index: usize) -> &mut V { + self.get_index_mut(index) + .expect("SortedVecMap: index out of bounds") + .1 + } +} + +impl Extend<(K, V)> for SortedVecMap +where + K: Ord, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.base + .extend(iterable.into_iter().map(|(k, v)| crate::Slot::new(k, v))); + } +} + +impl<'a, K: Clone + Ord, V: Clone> Extend<(&'a K, &'a V)> for SortedVecMap { + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.extend( + iterable + .into_iter() + .map(|(key, value)| (key.clone(), value.clone())), + ); + } +} + +impl<'a, K: Clone + Ord, V: Clone> Extend<&'a (K, V)> for SortedVecMap { + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.extend( + iterable + .into_iter() + .map(|(key, value)| (key.clone(), value.clone())), + ); + } +} + +impl FromIterator for SortedVecMap +where + Self: Extend, +{ + fn from_iter>(iter: I) -> Self { + let mut map = SortedVecMap::new(); + map.extend(iter); + map + } +} + +impl From> for SortedVecMap +where + K: Ord, +{ + /// Constructs a sorted map from a vector of `(key → value)` pairs. + /// + /// The input is sorted by key. When duplicate keys are present, the *last* occurrence wins + /// (matching the behaviour of inserting pairs one-by-one and of + /// [`BTreeMap::from_iter`](alloc::collections::BTreeMap::from_iter)). Runs in *O*(*n* log *n*). + fn from(vec: Vec<(K, V)>) -> Self { + // SAFETY: `Vec<(K, V)>` and `Vec>` have the same memory layout. + let base_vec: Vec> = unsafe { crate::transmute_vec(vec) }; + SortedVecMap { + base: base_vec.into(), + } + } +} + +impl From<&[(K, V)]> for SortedVecMap +where + K: Clone + Ord, + V: Clone, +{ + fn from(slice: &[(K, V)]) -> Self { + SortedVecMap::from_iter(slice) + } +} + +impl From<&mut [(K, V)]> for SortedVecMap +where + K: Clone + Ord, + V: Clone, +{ + fn from(slice: &mut [(K, V)]) -> Self { + // False-positive, we're re-slicing on purpose. + #[allow(clippy::redundant_slicing)] + SortedVecMap::from_iter(&slice[..]) + } +} + +impl From<[(K, V); N]> for SortedVecMap +where + K: Ord, +{ + fn from(arr: [(K, V); N]) -> Self { + SortedVecMap::from_iter(arr) + } +} + +impl PartialEq for SortedVecMap +where + K: PartialEq, + V: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.base == other.base + } +} + +impl Eq for SortedVecMap +where + K: Eq, + V: Eq, +{ +} + +#[cfg(test)] +mod test { + use super::*; + use crate::sorted_map::Entry; + use alloc::vec; + use core::ops::Bound; + + #[test] + fn eq() { + assert_ne!(SortedVecMap::from([("a", 1)]), SortedVecMap::from([])); + assert_eq!( + SortedVecMap::from([("a", 1)]), + SortedVecMap::from([("a", 1)]) + ); + assert_eq!( + SortedVecMap::from([("a", 1), ("b", 2)]), + SortedVecMap::from([("b", 2), ("a", 1)]) + ); + } + + #[test] + fn ordered_iteration() { + let map = SortedVecMap::from([(3, "c"), (1, "a"), (2, "b")]); + let collected: alloc::vec::Vec<_> = map.iter().map(|(k, v)| (*k, *v)).collect(); + assert_eq!(collected, alloc::vec![(1, "a"), (2, "b"), (3, "c")]); + } + + // `From` and `FromIterator` must both resolve duplicate keys the same way: last value + // wins, matching the one-by-one `insert` behaviour and `BTreeMap::from_iter`. + #[test] + fn from_vec_keeps_last_value_on_duplicate() { + let map = SortedVecMap::from(vec![("a", 1), ("b", 2), ("a", 10), ("b", 20)]); + assert_eq!(map.len(), 2); + assert_eq!(map[&"a"], 10); + assert_eq!(map[&"b"], 20); + } + + #[test] + fn from_iter_keeps_last_value_on_duplicate() { + let map: SortedVecMap<_, _> = [("a", 1), ("b", 2), ("a", 10)].into_iter().collect(); + assert_eq!(map[&"a"], 10); + assert_eq!(map[&"b"], 2); + } + + // VacantEntry stores the insertion index from the binary search. Inserting through it must + // preserve the sort order at all positions — front, middle, and back. + #[test] + fn vacant_entry_insert_at_boundaries() { + let mut map: SortedVecMap = SortedVecMap::new(); + // Insert into empty (index 0). + assert!(matches!(map.entry(5), Entry::Vacant(_))); + map.entry(5).or_insert("five"); + + // Insert at front (index 0). + if let Entry::Vacant(v) = map.entry(1) { + assert_eq!(v.index(), 0); + v.insert("one"); + } else { + panic!("expected vacant"); + } + + // Insert at back (index len). + if let Entry::Vacant(v) = map.entry(10) { + assert_eq!(v.index(), 2); + v.insert("ten"); + } else { + panic!("expected vacant"); + } + + // Insert in middle. + if let Entry::Vacant(v) = map.entry(7) { + assert_eq!(v.index(), 2); + v.insert("seven"); + } else { + panic!("expected vacant"); + } + + let collected: alloc::vec::Vec<_> = map.iter().map(|(k, v)| (*k, *v)).collect(); + assert_eq!( + collected, + vec![(1, "one"), (5, "five"), (7, "seven"), (10, "ten")] + ); + } + + #[test] + fn occupied_entry_replaces_in_place() { + let mut map = SortedVecMap::from([(1, "a"), (2, "b"), (3, "c")]); + match map.entry(2) { + Entry::Occupied(mut o) => { + assert_eq!(o.index(), 1); + assert_eq!(o.insert("B"), "b"); + } + Entry::Vacant(_) => panic!("expected occupied"), + } + assert_eq!(map[&2], "B"); + assert_eq!(map.as_slice(), &[(1, "a"), (2, "B"), (3, "c")]); + } + + // `range` with mixed inclusive/exclusive bounds on both sides. + #[test] + fn range_with_exclusive_bounds() { + let map = SortedVecMap::from([(1, 'a'), (3, 'c'), (5, 'e'), (7, 'g'), (9, 'i')]); + + let collected: alloc::vec::Vec<_> = map.range(3..=7).map(|(k, _)| *k).collect(); + assert_eq!(collected, vec![3, 5, 7]); + + let collected: alloc::vec::Vec<_> = map.range(3..7).map(|(k, _)| *k).collect(); + assert_eq!(collected, vec![3, 5]); + + // Both-exclusive range. + let collected: alloc::vec::Vec<_> = map + .range((Bound::Excluded(&3), Bound::Excluded(&7))) + .map(|(k, _)| *k) + .collect(); + assert_eq!(collected, vec![5]); + + // Unbounded ends. + let collected: alloc::vec::Vec<_> = map + .range((Bound::Unbounded, Bound::Included(&3))) + .map(|(k, _)| *k) + .collect(); + assert_eq!(collected, vec![1, 3]); + } + + #[test] + #[should_panic(expected = "range start is greater than range end")] + fn range_panics_on_reversed_bounds() { + let map = SortedVecMap::from([(1, 'a'), (3, 'c'), (5, 'e')]); + let (lo, hi) = (5, 3); + let _ = map.range(lo..hi); + } + + #[test] + fn range_mut_updates_values_without_disturbing_order() { + let mut map = SortedVecMap::from([(1, 0), (3, 0), (5, 0), (7, 0)]); + for (_, v) in map.range_mut(3..=5) { + *v = 100; + } + assert_eq!(map[&1], 0); + assert_eq!(map[&3], 100); + assert_eq!(map[&5], 100); + assert_eq!(map[&7], 0); + // Sort order preserved. + let keys: alloc::vec::Vec<_> = map.keys().copied().collect(); + assert_eq!(keys, vec![1, 3, 5, 7]); + } + + // `append` must preserve sort order, apply BTreeMap-style "other wins" semantics on + // overlapping keys, and leave `other` empty. + #[test] + fn append_with_overlap_other_wins() { + let mut a = SortedVecMap::from([(1, "a"), (3, "c"), (5, "e")]); + let mut b = SortedVecMap::from([(3, "C"), (4, "d"), (6, "f")]); + a.append(&mut b); + + assert!(b.is_empty()); + assert_eq!( + a.as_slice(), + &[(1, "a"), (3, "C"), (4, "d"), (5, "e"), (6, "f")] + ); + } + + #[test] + fn append_empty_other() { + let mut a = SortedVecMap::from([(1, "a"), (2, "b")]); + let mut b: SortedVecMap = SortedVecMap::new(); + a.append(&mut b); + assert_eq!(a.len(), 2); + } + + #[test] + fn append_empty_self() { + let mut a: SortedVecMap = SortedVecMap::new(); + let mut b = SortedVecMap::from([(1, "a"), (2, "b")]); + a.append(&mut b); + assert_eq!(a.len(), 2); + assert!(b.is_empty()); + } + + #[test] + fn retain_preserves_sort_order() { + let mut map: SortedVecMap = (0..10).map(|x| (x, x * 10)).collect(); + map.retain(|&k, _| k % 3 == 0); + let keys: alloc::vec::Vec<_> = map.keys().copied().collect(); + assert_eq!(keys, vec![0, 3, 6, 9]); + } + + #[test] + fn drain_with_empty_range_leaves_map_untouched() { + let mut map = SortedVecMap::from([(1, "a"), (2, "b"), (3, "c")]); + let collected: alloc::vec::Vec<_> = map.drain(1..1).collect(); + assert!(collected.is_empty()); + assert_eq!(map.len(), 3); + } + + #[test] + fn first_and_last_mutable() { + let mut map = SortedVecMap::from([(1, 10), (2, 20), (3, 30)]); + if let Some((k, v)) = map.first_key_value_mut() { + assert_eq!(*k, 1); + *v = 100; + } + if let Some((k, v)) = map.last_key_value_mut() { + assert_eq!(*k, 3); + *v = 300; + } + assert_eq!(map[&1], 100); + assert_eq!(map[&3], 300); + } + + #[test] + fn pop_first_and_last_ordering() { + let mut map = SortedVecMap::from([(2, 'b'), (1, 'a'), (3, 'c')]); + assert_eq!(map.pop_first(), Some((1, 'a'))); + assert_eq!(map.pop_last(), Some((3, 'c'))); + assert_eq!(map.pop_first(), Some((2, 'b'))); + assert_eq!(map.pop_first(), None); + assert_eq!(map.pop_last(), None); + } + + // PartialEq is relaxed to K: PartialEq — we must be able to compare maps whose key type is + // PartialEq but not Ord. + #[test] + fn partial_eq_does_not_require_ord_on_value() { + // Floats are PartialEq but not Ord; keys are integers (Ord), values are f64 (PartialEq). + let a = SortedVecMap::from([(1_u8, 1.5_f64), (2, 2.5)]); + let b = SortedVecMap::from([(1_u8, 1.5_f64), (2, 2.5)]); + assert!(a == b); + } +} diff --git a/src/sorted_map/iter.rs b/src/sorted_map/iter.rs new file mode 100644 index 0000000..de3e93f --- /dev/null +++ b/src/sorted_map/iter.rs @@ -0,0 +1,367 @@ +use super::{Entries, Slot, SortedVecMap}; +use alloc::vec::{self, Vec}; +use core::fmt; +use core::iter::FusedIterator; +use core::ops::RangeBounds; +use core::slice; + +macro_rules! impl_iterator { + ($ty:ident<$($lt:lifetime,)*$($gen:ident),+>, $item:ty, $map:expr) => { + impl_iterator!($ty<$($lt,)*$($gen),+>, $item, $map, $map); + }; + ($ty:ident<$($lt:lifetime,)*$($gen:ident),+>, $item:ty, $map:expr, $debug_map:expr) => { + impl<$($lt,)*$($gen),+> Iterator for $ty<$($lt,)*$($gen),+> { + type Item = $item; + + fn next(&mut self) -> Option { + self.iter.next().map($map) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + } + + impl<$($lt,)*$($gen),+> DoubleEndedIterator for $ty<$($lt,)*$($gen),+> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map($map) + } + } + + impl<$($lt,)*$($gen),+> ExactSizeIterator for $ty<$($lt,)*$($gen),+> { + fn len(&self) -> usize { + self.iter.len() + } + } + + impl<$($lt,)*$($gen),+> FusedIterator for $ty<$($lt,)*$($gen),+> {} + + impl<$($lt,)*$($gen),+> fmt::Debug for $ty<$($lt,)*$($gen),+> + where + K: fmt::Debug, + V: fmt::Debug, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let iter = self.iter.as_slice().iter().map($debug_map); + f.debug_list().entries(iter).finish() + } + } + }; +} + +impl IntoIterator for SortedVecMap { + type Item = (K, V); + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self.into_entries()) + } +} + +impl<'a, K, V> IntoIterator for &'a SortedVecMap { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, K, V> IntoIterator for &'a mut SortedVecMap { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +/// An iterator over the entries of a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`iter`] method on [`SortedVecMap`]. +/// +/// [`iter`]: SortedVecMap::iter +pub struct Iter<'a, K, V> { + iter: slice::Iter<'a, Slot>, +} + +impl<'a, K, V> Iter<'a, K, V> { + pub(super) fn new(entries: &'a [Slot]) -> Iter<'a, K, V> { + Iter { + iter: entries.iter(), + } + } +} + +impl Clone for Iter<'_, K, V> { + fn clone(&self) -> Self { + Iter { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Iter<'a, K, V>, (&'a K, &'a V), Slot::refs); + +/// A mutable iterator over the entries of a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`iter_mut`] method on [`SortedVecMap`]. +/// +/// [`iter_mut`]: SortedVecMap::iter_mut +pub struct IterMut<'a, K, V> { + iter: slice::IterMut<'a, Slot>, +} + +impl<'a, K, V> IterMut<'a, K, V> { + pub(super) fn new(entries: &'a mut [Slot]) -> IterMut<'a, K, V> { + IterMut { + iter: entries.iter_mut(), + } + } +} + +impl_iterator!( + IterMut<'a, K, V>, + (&'a K, &'a mut V), + Slot::ref_mut, + Slot::refs +); + +/// An owning iterator over the entries of a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`into_iter`] method on [`SortedVecMap`]. +/// +/// [`into_iter`]: IntoIterator::into_iter +pub struct IntoIter { + iter: vec::IntoIter>, +} + +impl IntoIter { + pub(super) fn new(entries: Vec>) -> IntoIter { + IntoIter { + iter: entries.into_iter(), + } + } +} + +impl Clone for IntoIter +where + K: Clone, + V: Clone, +{ + fn clone(&self) -> Self { + IntoIter { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(IntoIter, (K, V), Slot::into_key_value, Slot::refs); + +/// An iterator over the keys of a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`keys`] method on [`SortedVecMap`]. +/// +/// [`keys`]: SortedVecMap::keys +pub struct Keys<'a, K, V> { + iter: slice::Iter<'a, Slot>, +} + +impl<'a, K, V> Keys<'a, K, V> { + pub(super) fn new(entries: &'a [Slot]) -> Keys<'a, K, V> { + Keys { + iter: entries.iter(), + } + } +} + +impl Clone for Keys<'_, K, V> { + fn clone(&self) -> Self { + Keys { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Keys<'a, K, V>, &'a K, Slot::key); + +/// An owning iterator over the keys of a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`into_keys`] method on [`SortedVecMap`]. +/// +/// [`into_keys`]: SortedVecMap::into_keys +pub struct IntoKeys { + iter: vec::IntoIter>, +} + +impl IntoKeys { + pub(super) fn new(entries: Vec>) -> IntoKeys { + IntoKeys { + iter: entries.into_iter(), + } + } +} + +impl Clone for IntoKeys +where + K: Clone, + V: Clone, +{ + fn clone(&self) -> Self { + IntoKeys { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(IntoKeys, K, Slot::into_key, Slot::key); + +/// An iterator over the values of a [`SortedVecMap`] in sort order. +/// +/// This `struct` is created by the [`values`] method on [`SortedVecMap`]. +/// +/// [`values`]: SortedVecMap::values +pub struct Values<'a, K, V> { + iter: slice::Iter<'a, Slot>, +} + +impl<'a, K, V> Values<'a, K, V> { + pub(super) fn new(entries: &'a [Slot]) -> Values<'a, K, V> { + Values { + iter: entries.iter(), + } + } +} + +impl Clone for Values<'_, K, V> { + fn clone(&self) -> Self { + Values { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Values<'a, K, V>, &'a V, Slot::value); + +/// A mutable iterator over the values of a [`SortedVecMap`] in sort order. +/// +/// This `struct` is created by the [`values_mut`] method on [`SortedVecMap`]. +/// +/// [`values_mut`]: SortedVecMap::values_mut +pub struct ValuesMut<'a, K, V> { + iter: slice::IterMut<'a, Slot>, +} + +impl<'a, K, V> ValuesMut<'a, K, V> { + pub(super) fn new(entries: &'a mut [Slot]) -> ValuesMut<'a, K, V> { + ValuesMut { + iter: entries.iter_mut(), + } + } +} + +impl_iterator!(ValuesMut<'a, K, V>, &'a mut V, Slot::value_mut, Slot::value); + +/// An owning iterator over the values of a [`SortedVecMap`] in sort order. +/// +/// This `struct` is created by the [`into_values`] method on [`SortedVecMap`]. +/// +/// [`into_values`]: SortedVecMap::into_values +pub struct IntoValues { + iter: vec::IntoIter>, +} + +impl IntoValues { + pub(super) fn new(entries: Vec>) -> IntoValues { + IntoValues { + iter: entries.into_iter(), + } + } +} + +impl Clone for IntoValues +where + K: Clone, + V: Clone, +{ + fn clone(&self) -> Self { + IntoValues { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(IntoValues, V, Slot::into_value, Slot::value); + +/// An iterator over a sub-range of entries in a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`range`] method on [`SortedVecMap`]. +/// +/// [`range`]: SortedVecMap::range +pub struct Range<'a, K, V> { + iter: slice::Iter<'a, Slot>, +} + +impl<'a, K, V> Range<'a, K, V> { + pub(super) fn new(entries: &'a [Slot]) -> Range<'a, K, V> { + Range { + iter: entries.iter(), + } + } +} + +impl Clone for Range<'_, K, V> { + fn clone(&self) -> Self { + Range { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Range<'a, K, V>, (&'a K, &'a V), Slot::refs); + +/// A mutable iterator over a sub-range of entries in a [`SortedVecMap`]. +/// +/// This `struct` is created by the [`range_mut`] method on [`SortedVecMap`]. +/// +/// [`range_mut`]: SortedVecMap::range_mut +pub struct RangeMut<'a, K, V> { + iter: slice::IterMut<'a, Slot>, +} + +impl<'a, K, V> RangeMut<'a, K, V> { + pub(super) fn new(entries: &'a mut [Slot]) -> RangeMut<'a, K, V> { + RangeMut { + iter: entries.iter_mut(), + } + } +} + +impl_iterator!( + RangeMut<'a, K, V>, + (&'a K, &'a mut V), + Slot::ref_mut, + Slot::refs +); + +/// A draining iterator for [`SortedVecMap`]. +/// +/// This `struct` is created by the [`drain`] method on [`SortedVecMap`]. +/// +/// [`drain`]: SortedVecMap::drain +pub struct Drain<'a, K, V> { + iter: vec::Drain<'a, Slot>, +} + +impl<'a, K, V> Drain<'a, K, V> { + pub(super) fn new(map: &'a mut SortedVecMap, range: R) -> Drain<'a, K, V> + where + R: RangeBounds, + { + Drain { + iter: map.base.drain(range), + } + } +} + +impl_iterator!(Drain<'a, K, V>, (K, V), Slot::into_key_value, Slot::refs); diff --git a/src/sorted_map/serde.rs b/src/sorted_map/serde.rs new file mode 100644 index 0000000..bcdbb4f --- /dev/null +++ b/src/sorted_map/serde.rs @@ -0,0 +1,102 @@ +use super::SortedVecMap; +use core::fmt; +use core::marker::PhantomData; +use serde::de::{self, value::MapDeserializer}; +use serde::ser; + +impl ser::Serialize for SortedVecMap +where + K: ser::Serialize + Ord, + V: ser::Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + serializer.collect_map(self) + } +} + +impl<'de, K, V> de::Deserialize<'de> for SortedVecMap +where + K: de::Deserialize<'de> + Ord, + V: de::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + struct SortedVecMapVisitor(PhantomData<(K, V)>); + + impl<'de, K, V> de::Visitor<'de> for SortedVecMapVisitor + where + K: de::Deserialize<'de> + Ord, + V: de::Deserialize<'de>, + { + type Value = SortedVecMap; + + fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str("a map") + } + + fn visit_map(self, mut map: A) -> Result + where + A: de::MapAccess<'de>, + { + let mut values = SortedVecMap::with_capacity(map.size_hint().unwrap_or(0)); + + while let Some((key, value)) = map.next_entry()? { + values.insert(key, value); + } + + Ok(values) + } + } + + deserializer.deserialize_map(SortedVecMapVisitor(PhantomData)) + } +} + +impl<'de, K, V, E> de::IntoDeserializer<'de, E> for SortedVecMap +where + K: de::IntoDeserializer<'de, E> + Ord, + V: de::IntoDeserializer<'de, E>, + E: de::Error, +{ + type Deserializer = MapDeserializer<'de, ::IntoIter, E>; + + fn into_deserializer(self) -> Self::Deserializer { + MapDeserializer::new(self.into_iter()) + } +} + +#[cfg(test)] +mod test { + use super::*; + use serde_test::{Token, assert_tokens}; + + #[test] + fn ser_de_empty() { + let map = SortedVecMap::::new(); + assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]); + } + + #[test] + fn ser_de() { + let map = SortedVecMap::from([("c", 3), ("a", 1), ("b", 2)]); + // Serializes in sorted-key order. + assert_tokens( + &map, + &[ + Token::Map { len: Some(3) }, + Token::BorrowedStr("a"), + Token::I32(1), + Token::BorrowedStr("b"), + Token::I32(2), + Token::BorrowedStr("c"), + Token::I32(3), + Token::MapEnd, + ], + ); + } +} diff --git a/src/sorted_set.rs b/src/sorted_set.rs new file mode 100644 index 0000000..f3897cb --- /dev/null +++ b/src/sorted_set.rs @@ -0,0 +1,648 @@ +//! `SortedVecSet` is a vector-based set implementation which keeps its elements sorted. + +mod impls; +mod iter; +#[cfg(feature = "serde")] +mod serde; + +use super::{Entries, TryReserveError, sorted_keyed::SortedKeyedVecSet}; +use alloc::vec::Vec; +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::ops::RangeBounds; + +pub use self::iter::*; + +/// A vector-based set implementation which keeps its elements sorted. +/// +/// Internally it is represented as a `Vec` kept sorted by `T`'s [`Ord`] implementation. +/// Iteration order matches the sort order. +/// +/// # Complexity +/// +/// | operation | cost | +/// |---------------------------------------------------------------|------------------| +/// | `get` / `contains` / `binary_search` | *O*(log *n*) | +/// | `insert` / `remove` / `pop_first` | *O*(*n*) (shift) | +/// | `pop_last` | *O*(1) | +/// | `append` | *O*(*n* + *m*) | +/// | `union` / `intersection` / `difference` / `is_subset` / ... | *O*(*n* + *m*) | +/// +/// Lookups are faster than [`VecSet`](crate::VecSet)'s linear scan, but writes pay a shift cost +/// that [`BTreeSet`](alloc::collections::BTreeSet) avoids. Set operations are merge-based and run +/// in linear time. +#[derive(Clone, Debug)] +pub struct SortedVecSet { + base: SortedKeyedVecSet, +} + +impl SortedVecSet { + /// Create a new set. (Does not allocate.) + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set: SortedVecSet<&str> = SortedVecSet::new(); + /// ``` + pub const fn new() -> Self { + SortedVecSet { + base: SortedKeyedVecSet::new(), + } + } + + /// Create a new set with capacity for `capacity` elements. (Does not allocate if `capacity` + /// is zero.) + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set: SortedVecSet<&str> = SortedVecSet::with_capacity(10); + /// assert_eq!(set.len(), 0); + /// assert!(set.capacity() >= 10); + /// ``` + pub fn with_capacity(capacity: usize) -> Self { + SortedVecSet { + base: SortedKeyedVecSet::with_capacity(capacity), + } + } + + /// Returns the number of elements the set can hold without reallocating. + pub fn capacity(&self) -> usize { + self.base.capacity() + } + + /// Returns the number of elements in the set. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut a = SortedVecSet::new(); + /// assert_eq!(a.len(), 0); + /// a.insert(1); + /// assert_eq!(a.len(), 1); + /// ``` + pub fn len(&self) -> usize { + self.base.len() + } + + /// Returns `true` if the set contains no elements. + pub fn is_empty(&self) -> bool { + self.base.is_empty() + } + + /// Clears the set, removing all elements. + pub fn clear(&mut self) { + self.base.clear(); + } + + /// Shortens the set, keeping the first `len` (smallest) elements and dropping the rest. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set = SortedVecSet::from(["d", "a", "c", "b"]); + /// set.truncate(2); + /// assert_eq!(set, SortedVecSet::from(["a", "b"])); + /// ``` + pub fn truncate(&mut self, len: usize) { + self.base.truncate(len); + } + + /// Reserves capacity for at least `additional` more elements. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + pub fn reserve(&mut self, additional: usize) { + self.base.reserve(additional); + } + + /// Reserves the minimum capacity for at least `additional` more elements. + /// + /// # Panics + /// + /// Panics if the new capacity exceeds `isize::MAX` bytes. + pub fn reserve_exact(&mut self, additional: usize) { + self.base.reserve_exact(additional); + } + + /// Tries to reserve capacity for at least `additional` more elements. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve(additional) + } + + /// Tries to reserve the minimum capacity for at least `additional` more elements. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error is returned. + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.base.try_reserve_exact(additional) + } + + /// Retains only the elements specified by the predicate. The sort order is preserved. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set: SortedVecSet = SortedVecSet::from([0, 1, 2, 3, 4, 5, 6, 7]); + /// set.retain(|&e| e % 2 == 0); + /// assert_eq!(set.len(), 4); + /// ``` + pub fn retain(&mut self, f: F) + where + F: FnMut(&T) -> bool, + { + self.base.retain(f); + } + + /// Shrinks the capacity of the set as much as possible. + pub fn shrink_to_fit(&mut self) { + self.base.shrink_to_fit(); + } + + /// Shrinks the capacity of the set with a lower limit. + pub fn shrink_to(&mut self, min_capacity: usize) { + self.base.shrink_to(min_capacity); + } + + /// Splits the set into two at the given index. + /// + /// Returns a newly allocated set containing the elements in the range `[at, len)`. Both + /// halves remain sorted. + /// + /// # Panics + /// + /// Panics if `at > len`. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set = SortedVecSet::from(["b", "a", "c"]); + /// let set2 = set.split_off(1); + /// assert_eq!(set, SortedVecSet::from(["a"])); + /// assert_eq!(set2, SortedVecSet::from(["b", "c"])); + /// ``` + pub fn split_off(&mut self, at: usize) -> SortedVecSet { + SortedVecSet { + base: self.base.split_off(at), + } + } + + /// Search over the set for a value. + /// + /// Returns the position where that value is present, or the position where it can be + /// inserted to maintain the sort. See [`slice::binary_search`] for more details. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let set = SortedVecSet::from(["a", "b", "d"]); + /// assert_eq!(set.binary_search(&"b"), Ok(1)); + /// assert_eq!(set.binary_search(&"c"), Err(2)); + /// ``` + pub fn binary_search(&self, value: &T) -> Result + where + T: Ord, + { + self.binary_search_by(|v| v.cmp(value)) + } + + /// Search over the set with a comparator function. + pub fn binary_search_by<'a, F>(&'a self, f: F) -> Result + where + F: FnMut(&'a T) -> Ordering, + { + self.as_slice().binary_search_by(f) + } + + /// Search over the set with an extraction function. + pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result + where + F: FnMut(&'a T) -> B, + B: Ord, + { + self.as_slice().binary_search_by_key(b, f) + } + + /// Returns the index of the partition point of the set according to the given predicate. + pub fn partition_point

(&self, pred: P) -> usize + where + P: FnMut(&T) -> bool, + { + self.as_slice().partition_point(pred) + } + + /// Removes the specified range from the vector in bulk, returning all removed elements as an + /// iterator. + /// + /// The range is interpreted in index space, not value space. + pub fn drain(&mut self, range: R) -> Drain<'_, T> + where + R: RangeBounds, + { + Drain::new(self, range) + } + + /// An iterator visiting all elements in sort order. The iterator element type is `&'a T`. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let set = SortedVecSet::from(["b", "a", "c"]); + /// + /// for elem in set.iter() { + /// println!("elem: {elem}"); + /// } + /// ``` + pub fn iter(&self) -> Iter<'_, T> { + Iter::new(self.as_entries()) + } + + /// Extracts a slice containing the set elements in sort order. + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let set = SortedVecSet::from(["b", "a", "c"]); + /// let slice = set.as_slice(); + /// assert_eq!(slice, ["a", "b", "c"]); + /// ``` + pub fn as_slice(&self) -> &[T] { + self.base.as_slice() + } + + /// Copies the set elements into a new `Vec` in sort order. + pub fn to_vec(&self) -> Vec + where + T: Clone, + { + self.base.to_vec() + } + + /// Takes ownership of the set and returns its elements as a `Vec` in sort order. + pub fn into_vec(self) -> Vec { + self.base.into_vec() + } + + /// Takes ownership of the provided vector and converts it into `SortedVecSet`. + /// + /// # Safety + /// + /// The vector must be sorted strictly (no duplicates). One way to guarantee this is to sort + /// the vector (e.g. by using [`[T]::sort`][slice-sort]) and then drop duplicate elements + /// (e.g. by using [`Vec::dedup`]). + /// + /// [slice-sort]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort + /// + /// # Example + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut vec = vec!["b", "a", "c", "b"]; + /// vec.sort(); + /// vec.dedup(); + /// // SAFETY: we've just sorted and deduplicated the vector. + /// let set = unsafe { SortedVecSet::from_vec_unchecked(vec) }; + /// + /// assert_eq!(set, SortedVecSet::from(["a", "b", "c"])); + /// ``` + pub unsafe fn from_vec_unchecked(vec: Vec) -> Self { + SortedVecSet { + base: unsafe { SortedKeyedVecSet::from_vec_unchecked(vec) }, + } + } +} + +// Lookup operations. +impl SortedVecSet { + /// Return `true` if an equivalent to `value` exists in the set. + pub fn contains(&self, value: &Q) -> bool + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.contains_key(value) + } + + /// Get the first (least) element in the set. + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let set = SortedVecSet::from_iter(["b", "a"]); + /// assert_eq!(set.first(), Some(&"a")); + /// ``` + pub fn first(&self) -> Option<&T> { + self.base.first() + } + + /// Get the last (greatest) element in the set. + pub fn last(&self) -> Option<&T> { + self.base.last() + } + + /// Returns a reference to the value in the set, if any, that is equal to the given value. + pub fn get(&self, value: &Q) -> Option<&T> + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get(value) + } + + /// Return references to the element stored at `index`, if it is present, else `None`. + pub fn get_index(&self, index: usize) -> Option<&T> { + self.base.get_index(index) + } + + /// Returns the index and a reference to the value in the set, if any, that is equal to the + /// given value. + pub fn get_full(&self, value: &Q) -> Option<(usize, &T)> + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get_full(value) + } + + /// Return item index, if it exists in the set. + pub fn get_index_of(&self, value: &Q) -> Option + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.get_index_of(value) + } +} + +// Removal operations. +impl SortedVecSet { + /// Removes the first (least) element from the set and returns it, or [`None`] if it is empty. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set = SortedVecSet::from_iter(["b", "a"]); + /// assert_eq!(set.pop_first(), Some("a")); + /// assert_eq!(set.pop_first(), Some("b")); + /// assert_eq!(set.pop_first(), None); + /// ``` + pub fn pop_first(&mut self) -> Option { + self.base.pop_first() + } + + /// Removes the last (greatest) element from the set and returns it, or [`None`] if it is + /// empty. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set = SortedVecSet::from_iter(["b", "a"]); + /// assert_eq!(set.pop_last(), Some("b")); + /// assert_eq!(set.pop_last(), Some("a")); + /// assert_eq!(set.pop_last(), None); + /// ``` + pub fn pop_last(&mut self) -> Option { + self.base.pop_last() + } + + /// Remove the element equivalent to `value`. + /// + /// The element is removed by shifting all of the elements that follow it, preserving their + /// relative order (and therefore the sort invariant). + /// + /// Returns `true` if `value` was found in the set. + pub fn remove(&mut self, value: &Q) -> bool + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.remove(value).is_some() + } + + /// Removes and returns the element at position `index`, shifting all elements after it to the + /// left. + /// + /// # Panics + /// + /// Panics if `index` is out of bounds. + pub fn remove_index(&mut self, index: usize) -> T { + self.base.remove_index(index) + } + + /// Removes and returns the value in the set, if any, that is equal to the given one. + pub fn take(&mut self, value: &Q) -> Option + where + T: Ord + Borrow, + Q: Ord + ?Sized, + { + self.base.remove(value) + } +} + +// Insertion operations. +impl SortedVecSet +where + T: Ord, +{ + /// Adds a value to the set. + /// + /// Returns whether the value was newly inserted. That is: + /// + /// - If the set did not previously contain this value, `true` is returned. + /// - If the set already contained this value, `false` is returned. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let mut set = SortedVecSet::new(); + /// + /// assert_eq!(set.insert(2), true); + /// assert_eq!(set.insert(2), false); + /// assert_eq!(set.len(), 1); + /// ``` + pub fn insert(&mut self, value: T) -> bool { + self.base.insert(value).is_none() + } + + /// Moves all values from `other` into `self`, leaving `other` empty. + /// + /// When a value exists in both sets, the one from `other` replaces the one in `self` + /// (matching [`BTreeSet::append`](alloc::collections::BTreeSet::append) semantics). + pub fn append(&mut self, other: &mut SortedVecSet) { + self.base.append(&mut other.base); + } +} + +// Range iterators. +impl SortedVecSet +where + T: Ord, +{ + /// Constructs an iterator over a sub-range of elements in the set. + /// + /// The simplest way is to use the range syntax `min..max`. The range may also be specified as + /// `(Bound<&T>, Bound<&T>)` for more control over which bounds are inclusive. + /// + /// # Panics + /// + /// Panics if the range's start is greater than its end. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// + /// let set: SortedVecSet<_> = [3, 5, 8].into_iter().collect(); + /// let collected: Vec<_> = set.range(4..9).copied().collect(); + /// assert_eq!(collected, vec![5, 8]); + /// ``` + pub fn range(&self, range: R) -> Range<'_, T> + where + T: Borrow, + Q: Ord + ?Sized, + R: RangeBounds, + { + let (start, end) = self.base.key_range_to_indices(range); + Range::new(&self.base.as_slice()[start..end]) + } +} + +// Set operations. +impl SortedVecSet +where + T: Ord, +{ + /// Visits the values representing the difference, i.e., the values that are in `self` but not + /// in `other`. + /// + /// # Examples + /// + /// ``` + /// use vecmap::SortedVecSet; + /// let a = SortedVecSet::from([1, 2, 3]); + /// let b = SortedVecSet::from([4, 2, 3]); + /// + /// let diff: SortedVecSet<_> = a.difference(&b).copied().collect(); + /// assert_eq!(diff, SortedVecSet::from([1])); + /// ``` + pub fn difference<'a>(&'a self, other: &'a SortedVecSet) -> Difference<'a, T> { + Difference::new(self, other) + } + + /// Visits the values representing the intersection. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn intersection<'a>(&'a self, other: &'a SortedVecSet) -> Intersection<'a, T> { + Intersection::new(self, other) + } + + /// Visits the values representing the symmetric difference. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn symmetric_difference<'a>( + &'a self, + other: &'a SortedVecSet, + ) -> SymmetricDifference<'a, T> { + SymmetricDifference::new(self, other) + } + + /// Visits the values representing the union, in sort order with no duplicates. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn union<'a>(&'a self, other: &'a SortedVecSet) -> Union<'a, T> { + Union::new(self, other) + } + + /// Returns `true` if `self` has no elements in common with `other`. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn is_disjoint(&self, other: &SortedVecSet) -> bool { + let mut a = self.as_slice().iter(); + let mut b = other.as_slice().iter(); + let (mut x, mut y) = (a.next(), b.next()); + while let (Some(xv), Some(yv)) = (x, y) { + match xv.cmp(yv) { + Ordering::Less => x = a.next(), + Ordering::Greater => y = b.next(), + Ordering::Equal => return false, + } + } + true + } + + /// Returns `true` if the set is a subset of another. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn is_subset(&self, other: &SortedVecSet) -> bool { + if self.len() > other.len() { + return false; + } + let mut a = self.as_slice().iter().peekable(); + let mut b = other.as_slice().iter(); + while let Some(xv) = a.peek() { + match b.next() { + None => return false, + Some(yv) => match xv.cmp(&yv) { + Ordering::Less => return false, + Ordering::Equal => { + a.next(); + } + Ordering::Greater => {} + }, + } + } + true + } + + /// Returns `true` if the set is a superset of another. + /// + /// Runs in *O*(*n* + *m*) by walking both sorted sides in parallel. + pub fn is_superset(&self, other: &SortedVecSet) -> bool { + other.is_subset(self) + } +} + +impl Entries for SortedVecSet { + type Entry = T; + + fn as_entries(&self) -> &[Self::Entry] { + self.base.as_slice() + } + + fn as_entries_mut(&mut self) -> &mut [Self::Entry] { + self.base.as_mut_slice() + } + + fn into_entries(self) -> Vec { + self.base.into_vec() + } +} diff --git a/src/sorted_set/impls.rs b/src/sorted_set/impls.rs new file mode 100644 index 0000000..f7e6551 --- /dev/null +++ b/src/sorted_set/impls.rs @@ -0,0 +1,363 @@ +use core::ops::{BitAnd, BitOr, BitXor, Index, Sub}; + +use super::SortedVecSet; +use alloc::vec::Vec; + +impl Default for SortedVecSet { + fn default() -> Self { + SortedVecSet::new() + } +} + +impl Index for SortedVecSet { + type Output = T; + + fn index(&self, index: usize) -> &T { + self.get_index(index) + .expect("SortedVecSet: index out of bounds") + } +} + +impl Extend for SortedVecSet +where + T: Ord, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.base.extend(iterable); + } +} + +impl<'a, T> Extend<&'a T> for SortedVecSet +where + T: 'a + Copy + Ord, +{ + fn extend(&mut self, iterable: I) + where + I: IntoIterator, + { + self.base.extend(iterable.into_iter().copied()); + } +} + +impl FromIterator for SortedVecSet +where + T: Ord, +{ + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + SortedVecSet { + base: super::SortedKeyedVecSet::from_iter(iter), + } + } +} + +impl From> for SortedVecSet +where + T: Ord, +{ + /// Constructs a sorted set from a vector. + /// + /// The vector is sorted and deduplicated internally. Runs in *O*(*n* log *n*). + fn from(vec: Vec) -> Self { + SortedVecSet { base: vec.into() } + } +} + +impl From<&[T]> for SortedVecSet +where + T: Clone + Ord, +{ + fn from(slice: &[T]) -> Self { + SortedVecSet { base: slice.into() } + } +} + +impl From<&mut [T]> for SortedVecSet +where + T: Clone + Ord, +{ + fn from(slice: &mut [T]) -> Self { + SortedVecSet { base: slice.into() } + } +} + +impl From<[T; N]> for SortedVecSet +where + T: Ord, +{ + fn from(arr: [T; N]) -> Self { + SortedVecSet { base: arr.into() } + } +} + +impl PartialEq for SortedVecSet +where + T: PartialEq, +{ + fn eq(&self, other: &SortedVecSet) -> bool { + self.base == other.base + } +} + +impl Eq for SortedVecSet where T: Eq {} + +impl BitAnd<&SortedVecSet> for &SortedVecSet +where + T: Ord + Clone, +{ + type Output = SortedVecSet; + + /// Returns the set intersection, cloned into a new set. + fn bitand(self, other: &SortedVecSet) -> Self::Output { + self.intersection(other).cloned().collect() + } +} + +impl BitOr<&SortedVecSet> for &SortedVecSet +where + T: Ord + Clone, +{ + type Output = SortedVecSet; + + /// Returns the set union, cloned into a new set. + fn bitor(self, other: &SortedVecSet) -> Self::Output { + self.union(other).cloned().collect() + } +} + +impl BitXor<&SortedVecSet> for &SortedVecSet +where + T: Ord + Clone, +{ + type Output = SortedVecSet; + + /// Returns the set symmetric-difference, cloned into a new set. + fn bitxor(self, other: &SortedVecSet) -> Self::Output { + self.symmetric_difference(other).cloned().collect() + } +} + +impl Sub<&SortedVecSet> for &SortedVecSet +where + T: Ord + Clone, +{ + type Output = SortedVecSet; + + /// Returns the set difference, cloned into a new set. + fn sub(self, other: &SortedVecSet) -> Self::Output { + self.difference(other).cloned().collect() + } +} + +#[cfg(test)] +mod test { + use super::*; + use alloc::vec; + use core::ops::Bound; + + #[test] + fn ordered_iteration() { + let set = SortedVecSet::from([3, 1, 2]); + let v: alloc::vec::Vec<_> = set.iter().copied().collect(); + assert_eq!(v, alloc::vec![1, 2, 3]); + } + + #[test] + fn from_vec_dedup() { + let set = SortedVecSet::from(alloc::vec![3, 1, 2, 1, 3]); + assert_eq!(set.len(), 3); + assert_eq!(set.as_slice(), &[1, 2, 3]); + } + + fn collect<'a, I: IntoIterator>(iter: I) -> alloc::vec::Vec { + iter.into_iter().copied().collect() + } + + // Merge-based set-op iterators: verify correctness on disjoint, overlapping, equal, and empty + // inputs. + #[test] + fn intersection_disjoint() { + let a = SortedVecSet::from([1, 3, 5]); + let b = SortedVecSet::from([2, 4, 6]); + assert!(a.intersection(&b).next().is_none()); + } + + #[test] + fn intersection_overlapping() { + let a = SortedVecSet::from([1, 2, 3, 4, 5]); + let b = SortedVecSet::from([2, 4, 6]); + assert_eq!(collect(a.intersection(&b)), vec![2, 4]); + // Symmetric. + assert_eq!(collect(b.intersection(&a)), vec![2, 4]); + } + + #[test] + fn intersection_equal_sets() { + let a = SortedVecSet::from([1, 2, 3]); + assert_eq!(collect(a.intersection(&a)), vec![1, 2, 3]); + } + + #[test] + fn intersection_with_empty() { + let a = SortedVecSet::from([1, 2, 3]); + let b: SortedVecSet = SortedVecSet::new(); + assert!(a.intersection(&b).next().is_none()); + assert!(b.intersection(&a).next().is_none()); + } + + #[test] + fn difference_overlapping() { + let a = SortedVecSet::from([1, 2, 3, 4, 5]); + let b = SortedVecSet::from([2, 4, 6]); + assert_eq!(collect(a.difference(&b)), vec![1, 3, 5]); + assert_eq!(collect(b.difference(&a)), vec![6]); + } + + #[test] + fn difference_with_empty() { + let a = SortedVecSet::from([1, 2, 3]); + let b: SortedVecSet = SortedVecSet::new(); + assert_eq!(collect(a.difference(&b)), vec![1, 2, 3]); + assert!(b.difference(&a).next().is_none()); + } + + #[test] + fn union_preserves_order_and_dedups() { + let a = SortedVecSet::from([1, 3, 5]); + let b = SortedVecSet::from([2, 3, 4]); + assert_eq!(collect(a.union(&b)), vec![1, 2, 3, 4, 5]); + } + + #[test] + fn union_with_empty() { + let a = SortedVecSet::from([1, 2, 3]); + let b: SortedVecSet = SortedVecSet::new(); + assert_eq!(collect(a.union(&b)), vec![1, 2, 3]); + assert_eq!(collect(b.union(&a)), vec![1, 2, 3]); + } + + #[test] + fn symmetric_difference_in_sorted_order() { + let a = SortedVecSet::from([1, 2, 3, 4]); + let b = SortedVecSet::from([3, 4, 5, 6]); + assert_eq!(collect(a.symmetric_difference(&b)), vec![1, 2, 5, 6]); + } + + #[test] + fn is_subset_and_superset() { + let a = SortedVecSet::from([1, 2, 3]); + let b = SortedVecSet::from([1, 2, 3, 4, 5]); + assert!(a.is_subset(&b)); + assert!(b.is_superset(&a)); + assert!(!b.is_subset(&a)); + assert!(!a.is_superset(&b)); + // Proper-subset-like edge: equal sets are subsets of each other. + assert!(a.is_subset(&a)); + // Disjoint. + let c = SortedVecSet::from([10, 20]); + assert!(!c.is_subset(&a)); + // Subset of empty. + let empty: SortedVecSet = SortedVecSet::new(); + assert!(empty.is_subset(&a)); + assert!(!a.is_subset(&empty)); + } + + #[test] + fn is_disjoint_merge_walk() { + let a = SortedVecSet::from([1, 3, 5]); + let b = SortedVecSet::from([2, 4, 6]); + assert!(a.is_disjoint(&b)); + let c = SortedVecSet::from([5, 7]); + assert!(!a.is_disjoint(&c)); + let empty: SortedVecSet = SortedVecSet::new(); + assert!(a.is_disjoint(&empty)); + } + + #[test] + fn range_with_exclusive_bounds() { + let set = SortedVecSet::from([1, 3, 5, 7, 9]); + + let collected: alloc::vec::Vec<_> = set.range(3..7).copied().collect(); + assert_eq!(collected, vec![3, 5]); + + let collected: alloc::vec::Vec<_> = set + .range((Bound::Excluded(&3), Bound::Excluded(&9))) + .copied() + .collect(); + assert_eq!(collected, vec![5, 7]); + } + + #[test] + #[should_panic(expected = "range start is greater than range end")] + fn range_panics_on_reversed_bounds() { + let set = SortedVecSet::from([1, 3, 5]); + let (lo, hi) = (5, 3); + let _ = set.range(lo..hi); + } + + #[test] + fn append_with_overlap_other_wins_sort_invariant() { + let mut a = SortedVecSet::from([1, 3, 5]); + let mut b = SortedVecSet::from([3, 4, 6]); + a.append(&mut b); + assert_eq!(a.as_slice(), &[1, 3, 4, 5, 6]); + assert!(b.is_empty()); + } + + #[test] + fn append_empty_sides() { + let mut a: SortedVecSet = SortedVecSet::new(); + let mut b = SortedVecSet::from([1, 2, 3]); + a.append(&mut b); + assert_eq!(a.as_slice(), &[1, 2, 3]); + assert!(b.is_empty()); + + let mut c = SortedVecSet::from([1, 2, 3]); + let mut d: SortedVecSet = SortedVecSet::new(); + c.append(&mut d); + assert_eq!(c.as_slice(), &[1, 2, 3]); + } + + #[test] + fn split_off_keeps_both_halves_sorted() { + let mut a = SortedVecSet::from([1, 2, 3, 4, 5]); + let b = a.split_off(3); + assert_eq!(a.as_slice(), &[1, 2, 3]); + assert_eq!(b.as_slice(), &[4, 5]); + } + + #[test] + fn drain_then_set_remains_sorted() { + let mut set = SortedVecSet::from([1, 2, 3, 4, 5]); + let drained: alloc::vec::Vec<_> = set.drain(1..4).collect(); + assert_eq!(drained, vec![2, 3, 4]); + assert_eq!(set.as_slice(), &[1, 5]); + } + + // Operator overloads use the iterators, so smoke-test them. + #[test] + fn operators_collect_correctly() { + let a = SortedVecSet::from([1, 2, 3, 4]); + let b = SortedVecSet::from([3, 4, 5, 6]); + assert_eq!(&a & &b, SortedVecSet::from([3, 4])); + assert_eq!(&a | &b, SortedVecSet::from([1, 2, 3, 4, 5, 6])); + assert_eq!(&a ^ &b, SortedVecSet::from([1, 2, 5, 6])); + assert_eq!(&a - &b, SortedVecSet::from([1, 2])); + } + + // `Difference`/`Intersection`/etc. are Clone — verify. + #[test] + fn iterator_clones_are_independent() { + let a = SortedVecSet::from([1, 2, 3, 4, 5]); + let b = SortedVecSet::from([2, 4]); + let diff = a.difference(&b); + let cloned = diff.clone(); + assert_eq!(collect(diff), vec![1, 3, 5]); + assert_eq!(collect(cloned), vec![1, 3, 5]); + } +} diff --git a/src/sorted_set/iter.rs b/src/sorted_set/iter.rs new file mode 100644 index 0000000..129445b --- /dev/null +++ b/src/sorted_set/iter.rs @@ -0,0 +1,453 @@ +use super::{Entries, SortedVecSet}; +use alloc::vec::{self, Vec}; +use core::cmp::Ordering; +use core::fmt; +use core::iter::FusedIterator; +use core::iter::Peekable; +use core::ops::RangeBounds; +use core::slice; + +macro_rules! impl_iterator { + ($ty:ident<$($lt:lifetime,)*$($gen:ident),+>, $item:ty) => { + impl<$($lt,)*$($gen),+> Iterator for $ty<$($lt,)*$($gen),+> { + type Item = $item; + + fn next(&mut self) -> Option { + self.iter.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } + } + + impl<$($lt,)*$($gen),+> DoubleEndedIterator for $ty<$($lt,)*$($gen),+> { + fn next_back(&mut self) -> Option { + self.iter.next_back() + } + } + + impl<$($lt,)*$($gen),+> ExactSizeIterator for $ty<$($lt,)*$($gen),+> { + fn len(&self) -> usize { + self.iter.len() + } + } + + impl<$($lt,)*$($gen),+> FusedIterator for $ty<$($lt,)*$($gen),+> {} + + impl<$($lt,)*$($gen),+> fmt::Debug for $ty<$($lt,)*$($gen),+> + where + T: fmt::Debug, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let iter = self.iter.as_slice().iter(); + f.debug_list().entries(iter).finish() + } + } + }; +} + +impl IntoIterator for SortedVecSet { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> Self::IntoIter { + IntoIter::new(self.into_entries()) + } +} + +impl<'a, T> IntoIterator for &'a SortedVecSet { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +/// An iterator over the elements of a [`SortedVecSet`]. +/// +/// This `struct` is created by the [`iter`] method on [`SortedVecSet`]. +/// +/// [`iter`]: SortedVecSet::iter +pub struct Iter<'a, T> { + iter: slice::Iter<'a, T>, +} + +impl<'a, T> Iter<'a, T> { + pub(super) fn new(entries: &'a [T]) -> Iter<'a, T> { + Iter { + iter: entries.iter(), + } + } +} + +impl Clone for Iter<'_, T> { + fn clone(&self) -> Self { + Iter { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Iter<'a, T>, &'a T); + +/// An owning iterator over the elements of a [`SortedVecSet`]. +/// +/// This `struct` is created by the [`into_iter`] method on [`SortedVecSet`]. +/// +/// [`into_iter`]: IntoIterator::into_iter +pub struct IntoIter { + iter: vec::IntoIter, +} + +impl IntoIter { + pub(super) fn new(entries: Vec) -> IntoIter { + IntoIter { + iter: entries.into_iter(), + } + } +} + +impl Clone for IntoIter +where + T: Clone, +{ + fn clone(&self) -> Self { + IntoIter { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(IntoIter, T); + +/// An iterator over a sub-range of elements in a [`SortedVecSet`]. +/// +/// This `struct` is created by the [`range`] method on [`SortedVecSet`]. +/// +/// [`range`]: SortedVecSet::range +pub struct Range<'a, T> { + iter: slice::Iter<'a, T>, +} + +impl<'a, T> Range<'a, T> { + pub(super) fn new(entries: &'a [T]) -> Range<'a, T> { + Range { + iter: entries.iter(), + } + } +} + +impl Clone for Range<'_, T> { + fn clone(&self) -> Self { + Range { + iter: self.iter.clone(), + } + } +} + +impl_iterator!(Range<'a, T>, &'a T); + +/// A lazy iterator producing elements in the difference of [`SortedVecSet`]s. +/// +/// Both sides are walked in parallel, so this runs in *O*(*n* + *m*). +/// +/// This `struct` is created by the [`difference`] method on [`SortedVecSet`]. +/// +/// [`difference`]: SortedVecSet::difference +pub struct Difference<'a, T> { + iter: Peekable>, + other: Peekable>, +} + +impl<'a, T> Difference<'a, T> { + pub(super) fn new(set: &'a SortedVecSet, other: &'a SortedVecSet) -> Difference<'a, T> { + Difference { + iter: set.as_slice().iter().peekable(), + other: other.as_slice().iter().peekable(), + } + } +} + +impl<'a, T> Iterator for Difference<'a, T> +where + T: Ord, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + loop { + match (self.iter.peek(), self.other.peek()) { + (Some(s), Some(o)) => match s.cmp(o) { + Ordering::Less => return self.iter.next(), + Ordering::Equal => { + self.iter.next(); + self.other.next(); + } + Ordering::Greater => { + self.other.next(); + } + }, + (Some(_), None) => return self.iter.next(), + (None, _) => return None, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let self_len = self.iter.len(); + let other_len = self.other.len(); + (self_len.saturating_sub(other_len), Some(self_len)) + } +} + +impl FusedIterator for Difference<'_, T> where T: Ord {} + +impl Clone for Difference<'_, T> { + fn clone(&self) -> Self { + Difference { + iter: self.iter.clone(), + other: self.other.clone(), + } + } +} + +impl fmt::Debug for Difference<'_, T> +where + T: fmt::Debug + Ord, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A lazy iterator producing elements in the intersection of [`SortedVecSet`]s. +/// +/// Both sides are walked in parallel, so this runs in *O*(*n* + *m*). +/// +/// [`intersection`]: SortedVecSet::intersection +pub struct Intersection<'a, T> { + self_iter: Peekable>, + other_iter: Peekable>, +} + +impl<'a, T> Intersection<'a, T> { + pub(super) fn new(set: &'a SortedVecSet, other: &'a SortedVecSet) -> Intersection<'a, T> { + Intersection { + self_iter: set.as_slice().iter().peekable(), + other_iter: other.as_slice().iter().peekable(), + } + } +} + +impl<'a, T> Iterator for Intersection<'a, T> +where + T: Ord, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + loop { + match (self.self_iter.peek(), self.other_iter.peek()) { + (Some(s), Some(o)) => match s.cmp(o) { + Ordering::Less => { + self.self_iter.next(); + } + Ordering::Equal => { + self.other_iter.next(); + return self.self_iter.next(); + } + Ordering::Greater => { + self.other_iter.next(); + } + }, + _ => return None, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.self_iter.len().min(self.other_iter.len()))) + } +} + +impl FusedIterator for Intersection<'_, T> where T: Ord {} + +impl Clone for Intersection<'_, T> { + fn clone(&self) -> Self { + Intersection { + self_iter: self.self_iter.clone(), + other_iter: self.other_iter.clone(), + } + } +} + +impl fmt::Debug for Intersection<'_, T> +where + T: fmt::Debug + Ord, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A lazy iterator producing elements in the symmetric difference of [`SortedVecSet`]s. +/// +/// Both sides are walked in parallel, so this runs in *O*(*n* + *m*). +/// +/// [`symmetric_difference`]: SortedVecSet::symmetric_difference +pub struct SymmetricDifference<'a, T> { + iter: Peekable>, + other: Peekable>, +} + +impl<'a, T> SymmetricDifference<'a, T> { + pub(super) fn new( + set: &'a SortedVecSet, + other: &'a SortedVecSet, + ) -> SymmetricDifference<'a, T> { + SymmetricDifference { + iter: set.as_slice().iter().peekable(), + other: other.as_slice().iter().peekable(), + } + } +} + +impl<'a, T> Iterator for SymmetricDifference<'a, T> +where + T: Ord, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + loop { + match (self.iter.peek(), self.other.peek()) { + (Some(s), Some(o)) => match s.cmp(o) { + Ordering::Less => return self.iter.next(), + Ordering::Equal => { + self.iter.next(); + self.other.next(); + } + Ordering::Greater => return self.other.next(), + }, + (Some(_), None) => return self.iter.next(), + (None, Some(_)) => return self.other.next(), + (None, None) => return None, + } + } + } + + fn size_hint(&self) -> (usize, Option) { + (0, Some(self.iter.len() + self.other.len())) + } +} + +impl FusedIterator for SymmetricDifference<'_, T> where T: Ord {} + +impl Clone for SymmetricDifference<'_, T> { + fn clone(&self) -> Self { + SymmetricDifference { + iter: self.iter.clone(), + other: self.other.clone(), + } + } +} + +impl fmt::Debug for SymmetricDifference<'_, T> +where + T: fmt::Debug + Ord, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A lazy iterator producing elements in the union of [`SortedVecSet`]s, in sort order and with no +/// duplicates. +/// +/// Both sides are walked in parallel, so this runs in *O*(*n* + *m*). +/// +/// [`union`]: SortedVecSet::union +pub struct Union<'a, T> { + self_iter: Peekable>, + other_iter: Peekable>, +} + +impl<'a, T> Union<'a, T> { + pub(super) fn new(set: &'a SortedVecSet, other: &'a SortedVecSet) -> Union<'a, T> { + Union { + self_iter: set.as_slice().iter().peekable(), + other_iter: other.as_slice().iter().peekable(), + } + } +} + +impl<'a, T> Iterator for Union<'a, T> +where + T: Ord, +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + match (self.self_iter.peek(), self.other_iter.peek()) { + (Some(s), Some(o)) => match s.cmp(o) { + Ordering::Less => self.self_iter.next(), + Ordering::Equal => { + self.other_iter.next(); + self.self_iter.next() + } + Ordering::Greater => self.other_iter.next(), + }, + (Some(_), None) => self.self_iter.next(), + (None, Some(_)) => self.other_iter.next(), + (None, None) => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + let self_len = self.self_iter.len(); + let other_len = self.other_iter.len(); + (self_len.max(other_len), Some(self_len + other_len)) + } +} + +impl FusedIterator for Union<'_, T> where T: Ord {} + +impl Clone for Union<'_, T> { + fn clone(&self) -> Self { + Union { + self_iter: self.self_iter.clone(), + other_iter: self.other_iter.clone(), + } + } +} + +impl fmt::Debug for Union<'_, T> +where + T: fmt::Debug + Ord, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A draining iterator for [`SortedVecSet`]. +/// +/// [`drain`]: SortedVecSet::drain +pub struct Drain<'a, T> { + iter: vec::Drain<'a, T>, +} + +impl<'a, T> Drain<'a, T> { + pub(super) fn new(set: &'a mut SortedVecSet, range: R) -> Drain<'a, T> + where + R: RangeBounds, + { + Drain { + iter: set.base.drain(range), + } + } +} + +impl_iterator!(Drain<'a, T>, T); diff --git a/src/sorted_set/serde.rs b/src/sorted_set/serde.rs new file mode 100644 index 0000000..c5bc7c4 --- /dev/null +++ b/src/sorted_set/serde.rs @@ -0,0 +1,95 @@ +use super::SortedVecSet; +use core::fmt; +use core::marker::PhantomData; +use serde::de::{self, value::SeqDeserializer}; +use serde::ser; + +impl ser::Serialize for SortedVecSet +where + T: ser::Serialize + Ord, +{ + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + serializer.collect_seq(self) + } +} + +impl<'de, T> de::Deserialize<'de> for SortedVecSet +where + T: de::Deserialize<'de> + Ord, +{ + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + struct SortedVecSetVisitor(PhantomData); + + impl<'de, T> de::Visitor<'de> for SortedVecSetVisitor + where + T: de::Deserialize<'de> + Ord, + { + type Value = SortedVecSet; + + fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.write_str("a sequence") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: de::SeqAccess<'de>, + { + let mut values = SortedVecSet::with_capacity(seq.size_hint().unwrap_or(0)); + + while let Some(element) = seq.next_element()? { + values.insert(element); + } + + Ok(values) + } + } + + deserializer.deserialize_seq(SortedVecSetVisitor(PhantomData)) + } +} + +impl<'de, T, E> de::IntoDeserializer<'de, E> for SortedVecSet +where + T: de::IntoDeserializer<'de, E> + Ord, + E: de::Error, +{ + type Deserializer = SeqDeserializer<::IntoIter, E>; + + fn into_deserializer(self) -> Self::Deserializer { + SeqDeserializer::new(self.into_iter()) + } +} + +#[cfg(test)] +mod test { + use super::*; + use serde_test::{Token, assert_tokens}; + + #[test] + fn ser_de_empty() { + let set = SortedVecSet::<&str>::new(); + assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]); + } + + #[test] + fn ser_de() { + // Serializes in sorted order regardless of insertion order. + let set = SortedVecSet::from(["c", "a", "b"]); + assert_tokens( + &set, + &[ + Token::Seq { len: Some(3) }, + Token::BorrowedStr("a"), + Token::BorrowedStr("b"), + Token::BorrowedStr("c"), + Token::SeqEnd, + ], + ); + } +}