diff options
Diffstat (limited to 'vendor/im-rc/src/ord/set.rs')
-rw-r--r-- | vendor/im-rc/src/ord/set.rs | 1243 |
1 files changed, 1243 insertions, 0 deletions
diff --git a/vendor/im-rc/src/ord/set.rs b/vendor/im-rc/src/ord/set.rs new file mode 100644 index 000000000..60ad6adcc --- /dev/null +++ b/vendor/im-rc/src/ord/set.rs @@ -0,0 +1,1243 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +//! An ordered set. +//! +//! An immutable ordered set implemented as a [B-tree] [1]. +//! +//! Most operations on this type of set are O(log n). A +//! [`HashSet`][hashset::HashSet] is usually a better choice for +//! performance, but the `OrdSet` has the advantage of only requiring +//! an [`Ord`][std::cmp::Ord] constraint on its values, and of being +//! ordered, so values always come out from lowest to highest, where a +//! [`HashSet`][hashset::HashSet] has no guaranteed ordering. +//! +//! [1]: https://en.wikipedia.org/wiki/B-tree +//! [hashset::HashSet]: ./struct.HashSet.html +//! [std::cmp::Ord]: https://doc.rust-lang.org/std/cmp/trait.Ord.html + +use std::borrow::Borrow; +use std::cmp::Ordering; +use std::collections; +use std::fmt::{Debug, Error, Formatter}; +use std::hash::{BuildHasher, Hash, Hasher}; +use std::iter::{FromIterator, IntoIterator, Sum}; +use std::ops::{Add, Deref, Mul, RangeBounds}; + +use crate::hashset::HashSet; +use crate::nodes::btree::{ + BTreeValue, ConsumingIter as ConsumingNodeIter, DiffIter as NodeDiffIter, Insert, + Iter as NodeIter, Node, Remove, +}; +#[cfg(has_specialisation)] +use crate::util::linear_search_by; +use crate::util::{Pool, PoolRef}; + +pub use crate::nodes::btree::DiffItem; + +/// Construct a set from a sequence of values. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate im_rc as im; +/// # use im::ordset::OrdSet; +/// # fn main() { +/// assert_eq!( +/// ordset![1, 2, 3], +/// OrdSet::from(vec![1, 2, 3]) +/// ); +/// # } +/// ``` +#[macro_export] +macro_rules! ordset { + () => { $crate::ordset::OrdSet::new() }; + + ( $($x:expr),* ) => {{ + let mut l = $crate::ordset::OrdSet::new(); + $( + l.insert($x); + )* + l + }}; +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +struct Value<A>(A); + +impl<A> Deref for Value<A> { + type Target = A; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +// FIXME lacking specialisation, we can't simply implement `BTreeValue` +// for `A`, we have to use the `Value<A>` indirection. +#[cfg(not(has_specialisation))] +impl<A: Ord> BTreeValue for Value<A> { + type Key = A; + + fn ptr_eq(&self, _other: &Self) -> bool { + false + } + + fn search_key<BK>(slice: &[Self], key: &BK) -> Result<usize, usize> + where + BK: Ord + ?Sized, + Self::Key: Borrow<BK>, + { + slice.binary_search_by(|value| Self::Key::borrow(value).cmp(key)) + } + + fn search_value(slice: &[Self], key: &Self) -> Result<usize, usize> { + slice.binary_search_by(|value| value.cmp(key)) + } + + fn cmp_keys<BK>(&self, other: &BK) -> Ordering + where + BK: Ord + ?Sized, + Self::Key: Borrow<BK>, + { + Self::Key::borrow(self).cmp(other) + } + + fn cmp_values(&self, other: &Self) -> Ordering { + self.cmp(other) + } +} + +#[cfg(has_specialisation)] +impl<A: Ord> BTreeValue for Value<A> { + type Key = A; + + fn ptr_eq(&self, _other: &Self) -> bool { + false + } + + default fn search_key<BK>(slice: &[Self], key: &BK) -> Result<usize, usize> + where + BK: Ord + ?Sized, + Self::Key: Borrow<BK>, + { + slice.binary_search_by(|value| Self::Key::borrow(value).cmp(key)) + } + + default fn search_value(slice: &[Self], key: &Self) -> Result<usize, usize> { + slice.binary_search_by(|value| value.cmp(key)) + } + + fn cmp_keys<BK>(&self, other: &BK) -> Ordering + where + BK: Ord + ?Sized, + Self::Key: Borrow<BK>, + { + Self::Key::borrow(self).cmp(other) + } + + fn cmp_values(&self, other: &Self) -> Ordering { + self.cmp(other) + } +} + +#[cfg(has_specialisation)] +impl<A: Ord + Copy> BTreeValue for Value<A> { + fn search_key<BK>(slice: &[Self], key: &BK) -> Result<usize, usize> + where + BK: Ord + ?Sized, + Self::Key: Borrow<BK>, + { + linear_search_by(slice, |value| Self::Key::borrow(value).cmp(key)) + } + + fn search_value(slice: &[Self], key: &Self) -> Result<usize, usize> { + linear_search_by(slice, |value| value.cmp(key)) + } +} + +def_pool!(OrdSetPool<A>, Node<Value<A>>); + +/// An ordered set. +/// +/// An immutable ordered set implemented as a [B-tree] [1]. +/// +/// Most operations on this type of set are O(log n). A +/// [`HashSet`][hashset::HashSet] is usually a better choice for +/// performance, but the `OrdSet` has the advantage of only requiring +/// an [`Ord`][std::cmp::Ord] constraint on its values, and of being +/// ordered, so values always come out from lowest to highest, where a +/// [`HashSet`][hashset::HashSet] has no guaranteed ordering. +/// +/// [1]: https://en.wikipedia.org/wiki/B-tree +/// [hashset::HashSet]: ./struct.HashSet.html +/// [std::cmp::Ord]: https://doc.rust-lang.org/std/cmp/trait.Ord.html +pub struct OrdSet<A> { + size: usize, + pool: OrdSetPool<A>, + root: PoolRef<Node<Value<A>>>, +} + +impl<A> OrdSet<A> { + /// Construct an empty set. + #[must_use] + pub fn new() -> Self { + let pool = OrdSetPool::default(); + let root = PoolRef::default(&pool.0); + OrdSet { + size: 0, + pool, + root, + } + } + + /// Construct an empty set using a specific memory pool. + #[cfg(feature = "pool")] + #[must_use] + pub fn with_pool(pool: &OrdSetPool<A>) -> Self { + let root = PoolRef::default(&pool.0); + OrdSet { + size: 0, + pool: pool.clone(), + root, + } + } + + /// Construct a set with a single value. + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set = OrdSet::unit(123); + /// assert!(set.contains(&123)); + /// ``` + #[inline] + #[must_use] + pub fn unit(a: A) -> Self { + let pool = OrdSetPool::default(); + let root = PoolRef::new(&pool.0, Node::unit(Value(a))); + OrdSet { + size: 1, + pool, + root, + } + } + + /// Test whether a set is empty. + /// + /// Time: O(1) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// assert!( + /// !ordset![1, 2, 3].is_empty() + /// ); + /// assert!( + /// OrdSet::<i32>::new().is_empty() + /// ); + /// ``` + #[inline] + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Get the size of a set. + /// + /// Time: O(1) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// assert_eq!(3, ordset![1, 2, 3].len()); + /// ``` + #[inline] + #[must_use] + pub fn len(&self) -> usize { + self.size + } + + /// Test whether two sets refer to the same content in memory. + /// + /// This is true if the two sides are references to the same set, + /// or if the two sets refer to the same root node. + /// + /// This would return true if you're comparing a set to itself, or + /// if you're comparing a set to a fresh clone of itself. + /// + /// Time: O(1) + pub fn ptr_eq(&self, other: &Self) -> bool { + std::ptr::eq(self, other) || PoolRef::ptr_eq(&self.root, &other.root) + } + + /// Get a reference to the memory pool used by this set. + /// + /// Note that if you didn't specifically construct it with a pool, you'll + /// get back a reference to a pool of size 0. + #[cfg(feature = "pool")] + pub fn pool(&self) -> &OrdSetPool<A> { + &self.pool + } + + /// Discard all elements from the set. + /// + /// This leaves you with an empty set, and all elements that + /// were previously inside it are dropped. + /// + /// Time: O(n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::OrdSet; + /// let mut set = ordset![1, 2, 3]; + /// set.clear(); + /// assert!(set.is_empty()); + /// ``` + pub fn clear(&mut self) { + if !self.is_empty() { + self.root = PoolRef::default(&self.pool.0); + self.size = 0; + } + } +} + +impl<A> OrdSet<A> +where + A: Ord, +{ + /// Get the smallest value in a set. + /// + /// If the set is empty, returns `None`. + /// + /// Time: O(log n) + #[must_use] + pub fn get_min(&self) -> Option<&A> { + self.root.min().map(Deref::deref) + } + + /// Get the largest value in a set. + /// + /// If the set is empty, returns `None`. + /// + /// Time: O(log n) + #[must_use] + pub fn get_max(&self) -> Option<&A> { + self.root.max().map(Deref::deref) + } + + /// Create an iterator over the contents of the set. + #[must_use] + pub fn iter(&self) -> Iter<'_, A> { + Iter { + it: NodeIter::new(&self.root, self.size, ..), + } + } + + /// Create an iterator over a range inside the set. + #[must_use] + pub fn range<R, BA>(&self, range: R) -> RangedIter<'_, A> + where + R: RangeBounds<BA>, + A: Borrow<BA>, + BA: Ord + ?Sized, + { + RangedIter { + it: NodeIter::new(&self.root, self.size, range), + } + } + + /// Get an iterator over the differences between this set and + /// another, i.e. the set of entries to add or remove to this set + /// in order to make it equal to the other set. + /// + /// This function will avoid visiting nodes which are shared + /// between the two sets, meaning that even very large sets can be + /// compared quickly if most of their structure is shared. + /// + /// Time: O(n) (where n is the number of unique elements across + /// the two sets, minus the number of elements belonging to nodes + /// shared between them) + #[must_use] + pub fn diff<'a>(&'a self, other: &'a Self) -> DiffIter<'_, A> { + DiffIter { + it: NodeDiffIter::new(&self.root, &other.root), + } + } + + /// Test if a value is part of a set. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let mut set = ordset!{1, 2, 3}; + /// assert!(set.contains(&1)); + /// assert!(!set.contains(&4)); + /// ``` + #[inline] + #[must_use] + pub fn contains<BA>(&self, a: &BA) -> bool + where + BA: Ord + ?Sized, + A: Borrow<BA>, + { + self.root.lookup(a).is_some() + } + + /// Get the closest smaller value in a set to a given value. + /// + /// If the set contains the given value, this is returned. + /// Otherwise, the closest value in the set smaller than the + /// given value is returned. If the smallest value in the set + /// is larger than the given value, `None` is returned. + /// + /// # Examples + /// + /// ```rust + /// # #[macro_use] extern crate im_rc as im; + /// # use im::OrdSet; + /// let set = ordset![1, 3, 5, 7, 9]; + /// assert_eq!(Some(&5), set.get_prev(&6)); + /// ``` + #[must_use] + pub fn get_prev(&self, key: &A) -> Option<&A> { + self.root.lookup_prev(key).map(|v| &v.0) + } + + /// Get the closest larger value in a set to a given value. + /// + /// If the set contains the given value, this is returned. + /// Otherwise, the closest value in the set larger than the + /// given value is returned. If the largest value in the set + /// is smaller than the given value, `None` is returned. + /// + /// # Examples + /// + /// ```rust + /// # #[macro_use] extern crate im_rc as im; + /// # use im::OrdSet; + /// let set = ordset![1, 3, 5, 7, 9]; + /// assert_eq!(Some(&5), set.get_next(&4)); + /// ``` + #[must_use] + pub fn get_next(&self, key: &A) -> Option<&A> { + self.root.lookup_next(key).map(|v| &v.0) + } + + /// Test whether a set is a subset of another set, meaning that + /// all values in our set must also be in the other set. + /// + /// Time: O(n log m) where m is the size of the other set + #[must_use] + pub fn is_subset<RS>(&self, other: RS) -> bool + where + RS: Borrow<Self>, + { + let other = other.borrow(); + if other.len() < self.len() { + return false; + } + self.iter().all(|a| other.contains(a)) + } + + /// Test whether a set is a proper subset of another set, meaning + /// that all values in our set must also be in the other set. A + /// proper subset must also be smaller than the other set. + /// + /// Time: O(n log m) where m is the size of the other set + #[must_use] + pub fn is_proper_subset<RS>(&self, other: RS) -> bool + where + RS: Borrow<Self>, + { + self.len() != other.borrow().len() && self.is_subset(other) + } +} + +impl<A> OrdSet<A> +where + A: Ord + Clone, +{ + /// Insert a value into a set. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let mut set = ordset!{}; + /// set.insert(123); + /// set.insert(456); + /// assert_eq!( + /// set, + /// ordset![123, 456] + /// ); + /// ``` + #[inline] + pub fn insert(&mut self, a: A) -> Option<A> { + let new_root = { + let root = PoolRef::make_mut(&self.pool.0, &mut self.root); + match root.insert(&self.pool.0, Value(a)) { + Insert::Replaced(Value(old_value)) => return Some(old_value), + Insert::Added => { + self.size += 1; + return None; + } + Insert::Split(left, median, right) => PoolRef::new( + &self.pool.0, + Node::new_from_split(&self.pool.0, left, median, right), + ), + } + }; + self.size += 1; + self.root = new_root; + None + } + + /// Remove a value from a set. + /// + /// Time: O(log n) + #[inline] + pub fn remove<BA>(&mut self, a: &BA) -> Option<A> + where + BA: Ord + ?Sized, + A: Borrow<BA>, + { + let (new_root, removed_value) = { + let root = PoolRef::make_mut(&self.pool.0, &mut self.root); + match root.remove(&self.pool.0, a) { + Remove::Update(value, root) => (PoolRef::new(&self.pool.0, root), Some(value.0)), + Remove::Removed(value) => { + self.size -= 1; + return Some(value.0); + } + Remove::NoChange => return None, + } + }; + self.size -= 1; + self.root = new_root; + removed_value + } + + /// Remove the smallest value from a set. + /// + /// Time: O(log n) + pub fn remove_min(&mut self) -> Option<A> { + // FIXME implement this at the node level for better efficiency + let key = match self.get_min() { + None => return None, + Some(v) => v, + } + .clone(); + self.remove(&key) + } + + /// Remove the largest value from a set. + /// + /// Time: O(log n) + pub fn remove_max(&mut self) -> Option<A> { + // FIXME implement this at the node level for better efficiency + let key = match self.get_max() { + None => return None, + Some(v) => v, + } + .clone(); + self.remove(&key) + } + + /// Construct a new set from the current set with the given value + /// added. + /// + /// Time: O(log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set = ordset![456]; + /// assert_eq!( + /// set.update(123), + /// ordset![123, 456] + /// ); + /// ``` + #[must_use] + pub fn update(&self, a: A) -> Self { + let mut out = self.clone(); + out.insert(a); + out + } + + /// Construct a new set with the given value removed if it's in + /// the set. + /// + /// Time: O(log n) + #[must_use] + pub fn without<BA>(&self, a: &BA) -> Self + where + BA: Ord + ?Sized, + A: Borrow<BA>, + { + let mut out = self.clone(); + out.remove(a); + out + } + + /// Remove the smallest value from a set, and return that value as + /// well as the updated set. + /// + /// Time: O(log n) + #[must_use] + pub fn without_min(&self) -> (Option<A>, Self) { + match self.get_min() { + Some(v) => (Some(v.clone()), self.without(v)), + None => (None, self.clone()), + } + } + + /// Remove the largest value from a set, and return that value as + /// well as the updated set. + /// + /// Time: O(log n) + #[must_use] + pub fn without_max(&self) -> (Option<A>, Self) { + match self.get_max() { + Some(v) => (Some(v.clone()), self.without(v)), + None => (None, self.clone()), + } + } + + /// Construct the union of two sets. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set1 = ordset!{1, 2}; + /// let set2 = ordset!{2, 3}; + /// let expected = ordset!{1, 2, 3}; + /// assert_eq!(expected, set1.union(set2)); + /// ``` + #[must_use] + pub fn union(self, other: Self) -> Self { + let (mut to_mutate, to_consume) = if self.len() >= other.len() { + (self, other) + } else { + (other, self) + }; + for value in to_consume { + to_mutate.insert(value); + } + to_mutate + } + + /// Construct the union of multiple sets. + /// + /// Time: O(n log n) + #[must_use] + pub fn unions<I>(i: I) -> Self + where + I: IntoIterator<Item = Self>, + { + i.into_iter().fold(Self::default(), Self::union) + } + + /// Construct the symmetric difference between two sets. + /// + /// This is an alias for the + /// [`symmetric_difference`][symmetric_difference] method. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set1 = ordset!{1, 2}; + /// let set2 = ordset!{2, 3}; + /// let expected = ordset!{1, 3}; + /// assert_eq!(expected, set1.difference(set2)); + /// ``` + /// + /// [symmetric_difference]: #method.symmetric_difference + #[must_use] + pub fn difference(self, other: Self) -> Self { + self.symmetric_difference(other) + } + + /// Construct the symmetric difference between two sets. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set1 = ordset!{1, 2}; + /// let set2 = ordset!{2, 3}; + /// let expected = ordset!{1, 3}; + /// assert_eq!(expected, set1.symmetric_difference(set2)); + /// ``` + #[must_use] + pub fn symmetric_difference(mut self, other: Self) -> Self { + for value in other { + if self.remove(&value).is_none() { + self.insert(value); + } + } + self + } + + /// Construct the relative complement between two sets, that is the set + /// of values in `self` that do not occur in `other`. + /// + /// Time: O(m log n) where m is the size of the other set + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set1 = ordset!{1, 2}; + /// let set2 = ordset!{2, 3}; + /// let expected = ordset!{1}; + /// assert_eq!(expected, set1.relative_complement(set2)); + /// ``` + #[must_use] + pub fn relative_complement(mut self, other: Self) -> Self { + for value in other { + let _ = self.remove(&value); + } + self + } + + /// Construct the intersection of two sets. + /// + /// Time: O(n log n) + /// + /// # Examples + /// + /// ``` + /// # #[macro_use] extern crate im_rc as im; + /// # use im::ordset::OrdSet; + /// let set1 = ordset!{1, 2}; + /// let set2 = ordset!{2, 3}; + /// let expected = ordset!{2}; + /// assert_eq!(expected, set1.intersection(set2)); + /// ``` + #[must_use] + pub fn intersection(self, other: Self) -> Self { + let mut out = Self::default(); + for value in other { + if self.contains(&value) { + out.insert(value); + } + } + out + } + + /// Split a set into two, with the left hand set containing values + /// which are smaller than `split`, and the right hand set + /// containing values which are larger than `split`. + /// + /// The `split` value itself is discarded. + /// + /// Time: O(n) + #[must_use] + pub fn split<BA>(self, split: &BA) -> (Self, Self) + where + BA: Ord + ?Sized, + A: Borrow<BA>, + { + let (left, _, right) = self.split_member(split); + (left, right) + } + + /// Split a set into two, with the left hand set containing values + /// which are smaller than `split`, and the right hand set + /// containing values which are larger than `split`. + /// + /// Returns a tuple of the two sets and a boolean which is true if + /// the `split` value existed in the original set, and false + /// otherwise. + /// + /// Time: O(n) + #[must_use] + pub fn split_member<BA>(self, split: &BA) -> (Self, bool, Self) + where + BA: Ord + ?Sized, + A: Borrow<BA>, + { + let mut left = Self::default(); + let mut right = Self::default(); + let mut present = false; + for value in self { + match value.borrow().cmp(split) { + Ordering::Less => { + left.insert(value); + } + Ordering::Equal => { + present = true; + } + Ordering::Greater => { + right.insert(value); + } + } + } + (left, present, right) + } + + /// Construct a set with only the `n` smallest values from a given + /// set. + /// + /// Time: O(n) + #[must_use] + pub fn take(&self, n: usize) -> Self { + self.iter().take(n).cloned().collect() + } + + /// Construct a set with the `n` smallest values removed from a + /// given set. + /// + /// Time: O(n) + #[must_use] + pub fn skip(&self, n: usize) -> Self { + self.iter().skip(n).cloned().collect() + } +} + +// Core traits + +impl<A> Clone for OrdSet<A> { + /// Clone a set. + /// + /// Time: O(1) + #[inline] + fn clone(&self) -> Self { + OrdSet { + size: self.size, + pool: self.pool.clone(), + root: self.root.clone(), + } + } +} + +impl<A: Ord> PartialEq for OrdSet<A> { + fn eq(&self, other: &Self) -> bool { + PoolRef::ptr_eq(&self.root, &other.root) + || (self.len() == other.len() && self.diff(other).next().is_none()) + } +} + +impl<A: Ord + Eq> Eq for OrdSet<A> {} + +impl<A: Ord> PartialOrd for OrdSet<A> { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.iter().partial_cmp(other.iter()) + } +} + +impl<A: Ord> Ord for OrdSet<A> { + fn cmp(&self, other: &Self) -> Ordering { + self.iter().cmp(other.iter()) + } +} + +impl<A: Ord + Hash> Hash for OrdSet<A> { + fn hash<H>(&self, state: &mut H) + where + H: Hasher, + { + for i in self.iter() { + i.hash(state); + } + } +} + +impl<A> Default for OrdSet<A> { + fn default() -> Self { + OrdSet::new() + } +} + +impl<A: Ord + Clone> Add for OrdSet<A> { + type Output = OrdSet<A>; + + fn add(self, other: Self) -> Self::Output { + self.union(other) + } +} + +impl<'a, A: Ord + Clone> Add for &'a OrdSet<A> { + type Output = OrdSet<A>; + + fn add(self, other: Self) -> Self::Output { + self.clone().union(other.clone()) + } +} + +impl<A: Ord + Clone> Mul for OrdSet<A> { + type Output = OrdSet<A>; + + fn mul(self, other: Self) -> Self::Output { + self.intersection(other) + } +} + +impl<'a, A: Ord + Clone> Mul for &'a OrdSet<A> { + type Output = OrdSet<A>; + + fn mul(self, other: Self) -> Self::Output { + self.clone().intersection(other.clone()) + } +} + +impl<A: Ord + Clone> Sum for OrdSet<A> { + fn sum<I>(it: I) -> Self + where + I: Iterator<Item = Self>, + { + it.fold(Self::new(), |a, b| a + b) + } +} + +impl<A, R> Extend<R> for OrdSet<A> +where + A: Ord + Clone + From<R>, +{ + fn extend<I>(&mut self, iter: I) + where + I: IntoIterator<Item = R>, + { + for value in iter { + self.insert(From::from(value)); + } + } +} + +impl<A: Ord + Debug> Debug for OrdSet<A> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + f.debug_set().entries(self.iter()).finish() + } +} + +// Iterators + +/// An iterator over the elements of a set. +pub struct Iter<'a, A> { + it: NodeIter<'a, Value<A>>, +} + +impl<'a, A> Iterator for Iter<'a, A> +where + A: 'a + Ord, +{ + type Item = &'a A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + self.it.next().map(Deref::deref) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (self.it.remaining, Some(self.it.remaining)) + } +} + +impl<'a, A> DoubleEndedIterator for Iter<'a, A> +where + A: 'a + Ord, +{ + fn next_back(&mut self) -> Option<Self::Item> { + self.it.next_back().map(Deref::deref) + } +} + +impl<'a, A> ExactSizeIterator for Iter<'a, A> where A: 'a + Ord {} + +/// A ranged iterator over the elements of a set. +/// +/// The only difference from `Iter` is that this one doesn't implement +/// `ExactSizeIterator` because we can't know the size of the range without first +/// iterating over it to count. +pub struct RangedIter<'a, A> { + it: NodeIter<'a, Value<A>>, +} + +impl<'a, A> Iterator for RangedIter<'a, A> +where + A: 'a + Ord, +{ + type Item = &'a A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + self.it.next().map(Deref::deref) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.it.size_hint() + } +} + +impl<'a, A> DoubleEndedIterator for RangedIter<'a, A> +where + A: 'a + Ord, +{ + fn next_back(&mut self) -> Option<Self::Item> { + self.it.next_back().map(Deref::deref) + } +} + +/// A consuming iterator over the elements of a set. +pub struct ConsumingIter<A> { + it: ConsumingNodeIter<Value<A>>, +} + +impl<A> Iterator for ConsumingIter<A> +where + A: Ord + Clone, +{ + type Item = A; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + self.it.next().map(|v| v.0) + } +} + +/// An iterator over the difference between two sets. +pub struct DiffIter<'a, A> { + it: NodeDiffIter<'a, Value<A>>, +} + +impl<'a, A> Iterator for DiffIter<'a, A> +where + A: Ord + PartialEq, +{ + type Item = DiffItem<'a, A>; + + /// Advance the iterator and return the next value. + /// + /// Time: O(1)* + fn next(&mut self) -> Option<Self::Item> { + self.it.next().map(|item| match item { + DiffItem::Add(v) => DiffItem::Add(v.deref()), + DiffItem::Update { old, new } => DiffItem::Update { + old: old.deref(), + new: new.deref(), + }, + DiffItem::Remove(v) => DiffItem::Remove(v.deref()), + }) + } +} + +impl<A, R> FromIterator<R> for OrdSet<A> +where + A: Ord + Clone + From<R>, +{ + fn from_iter<T>(i: T) -> Self + where + T: IntoIterator<Item = R>, + { + let mut out = Self::new(); + for item in i { + out.insert(From::from(item)); + } + out + } +} + +impl<'a, A> IntoIterator for &'a OrdSet<A> +where + A: 'a + Ord, +{ + type Item = &'a A; + type IntoIter = Iter<'a, A>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<A> IntoIterator for OrdSet<A> +where + A: Ord + Clone, +{ + type Item = A; + type IntoIter = ConsumingIter<A>; + + fn into_iter(self) -> Self::IntoIter { + ConsumingIter { + it: ConsumingNodeIter::new(&self.root, self.size), + } + } +} + +// Conversions + +impl<'s, 'a, A, OA> From<&'s OrdSet<&'a A>> for OrdSet<OA> +where + A: ToOwned<Owned = OA> + Ord + ?Sized, + OA: Borrow<A> + Ord + Clone, +{ + fn from(set: &OrdSet<&A>) -> Self { + set.iter().map(|a| (*a).to_owned()).collect() + } +} + +impl<'a, A> From<&'a [A]> for OrdSet<A> +where + A: Ord + Clone, +{ + fn from(slice: &'a [A]) -> Self { + slice.iter().cloned().collect() + } +} + +impl<A: Ord + Clone> From<Vec<A>> for OrdSet<A> { + fn from(vec: Vec<A>) -> Self { + vec.into_iter().collect() + } +} + +impl<'a, A: Ord + Clone> From<&'a Vec<A>> for OrdSet<A> { + fn from(vec: &Vec<A>) -> Self { + vec.iter().cloned().collect() + } +} + +impl<A: Eq + Hash + Ord + Clone> From<collections::HashSet<A>> for OrdSet<A> { + fn from(hash_set: collections::HashSet<A>) -> Self { + hash_set.into_iter().collect() + } +} + +impl<'a, A: Eq + Hash + Ord + Clone> From<&'a collections::HashSet<A>> for OrdSet<A> { + fn from(hash_set: &collections::HashSet<A>) -> Self { + hash_set.iter().cloned().collect() + } +} + +impl<A: Ord + Clone> From<collections::BTreeSet<A>> for OrdSet<A> { + fn from(btree_set: collections::BTreeSet<A>) -> Self { + btree_set.into_iter().collect() + } +} + +impl<'a, A: Ord + Clone> From<&'a collections::BTreeSet<A>> for OrdSet<A> { + fn from(btree_set: &collections::BTreeSet<A>) -> Self { + btree_set.iter().cloned().collect() + } +} + +impl<A: Hash + Eq + Ord + Clone, S: BuildHasher> From<HashSet<A, S>> for OrdSet<A> { + fn from(hashset: HashSet<A, S>) -> Self { + hashset.into_iter().collect() + } +} + +impl<'a, A: Hash + Eq + Ord + Clone, S: BuildHasher> From<&'a HashSet<A, S>> for OrdSet<A> { + fn from(hashset: &HashSet<A, S>) -> Self { + hashset.into_iter().cloned().collect() + } +} + +// Proptest +#[cfg(any(test, feature = "proptest"))] +#[doc(hidden)] +pub mod proptest { + #[deprecated( + since = "14.3.0", + note = "proptest strategies have moved to im::proptest" + )] + pub use crate::proptest::ord_set; +} + +#[cfg(test)] +mod test { + use super::*; + use crate::proptest::*; + use ::proptest::proptest; + + #[test] + fn match_strings_with_string_slices() { + let mut set: OrdSet<String> = From::from(&ordset!["foo", "bar"]); + set = set.without("bar"); + assert!(!set.contains("bar")); + set.remove("foo"); + assert!(!set.contains("foo")); + } + + #[test] + fn ranged_iter() { + let set: OrdSet<i32> = ordset![1, 2, 3, 4, 5]; + let range: Vec<i32> = set.range(..).cloned().collect(); + assert_eq!(vec![1, 2, 3, 4, 5], range); + let range: Vec<i32> = set.range(..).rev().cloned().collect(); + assert_eq!(vec![5, 4, 3, 2, 1], range); + let range: Vec<i32> = set.range(2..5).cloned().collect(); + assert_eq!(vec![2, 3, 4], range); + let range: Vec<i32> = set.range(2..5).rev().cloned().collect(); + assert_eq!(vec![4, 3, 2], range); + let range: Vec<i32> = set.range(3..).cloned().collect(); + assert_eq!(vec![3, 4, 5], range); + let range: Vec<i32> = set.range(3..).rev().cloned().collect(); + assert_eq!(vec![5, 4, 3], range); + let range: Vec<i32> = set.range(..4).cloned().collect(); + assert_eq!(vec![1, 2, 3], range); + let range: Vec<i32> = set.range(..4).rev().cloned().collect(); + assert_eq!(vec![3, 2, 1], range); + let range: Vec<i32> = set.range(..=3).cloned().collect(); + assert_eq!(vec![1, 2, 3], range); + let range: Vec<i32> = set.range(..=3).rev().cloned().collect(); + assert_eq!(vec![3, 2, 1], range); + } + + proptest! { + #[test] + fn proptest_a_set(ref s in ord_set(".*", 10..100)) { + assert!(s.len() < 100); + assert!(s.len() >= 10); + } + + #[test] + fn long_ranged_iter(max in 1..1000) { + let range = 0..max; + let expected: Vec<i32> = range.clone().collect(); + let set: OrdSet<i32> = range.clone().collect::<OrdSet<_>>(); + let result: Vec<i32> = set.range(..).cloned().collect(); + assert_eq!(expected, result); + + let expected: Vec<i32> = range.clone().rev().collect(); + let set: OrdSet<i32> = range.collect::<OrdSet<_>>(); + let result: Vec<i32> = set.range(..).rev().cloned().collect(); + assert_eq!(expected, result); + } + } +} |