mod iter;
mod mutable;
mod slice;
#[cfg(test)]
mod tests;
pub use self::iter::{
Difference, Drain, ExtractIf, Intersection, IntoIter, Iter, Splice, SymmetricDifference, Union,
};
pub use self::mutable::MutableValues;
pub use self::slice::Slice;
use crate::TryReserveError;
#[cfg(feature = "rayon")]
pub use crate::rayon::set as rayon;
#[cfg(feature = "std")]
use std::hash::RandomState;
use alloc::boxed::Box;
use alloc::collections::VecDeque;
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{BuildHasher, Hash, Hasher};
use core::ops::{BitAnd, BitOr, BitXor, Index, RangeBounds, Sub};
use super::{Equivalent, RingMap};
type Bucket<T> = super::Bucket<T, ()>;
#[cfg(feature = "std")]
pub struct RingSet<T, S = RandomState> {
pub(crate) map: RingMap<T, (), S>,
}
#[cfg(not(feature = "std"))]
pub struct RingSet<T, S> {
pub(crate) map: RingMap<T, (), S>,
}
impl<T, S> Clone for RingSet<T, S>
where
T: Clone,
S: Clone,
{
fn clone(&self) -> Self {
RingSet {
map: self.map.clone(),
}
}
fn clone_from(&mut self, other: &Self) {
self.map.clone_from(&other.map);
}
}
impl<T, S> fmt::Debug for RingSet<T, S>
where
T: fmt::Debug,
{
#[cfg(not(feature = "test_debug"))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
#[cfg(feature = "test_debug")]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RingSet").field("map", &self.map).finish()
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> RingSet<T> {
pub fn new() -> Self {
RingSet {
map: RingMap::new(),
}
}
pub fn with_capacity(n: usize) -> Self {
RingSet {
map: RingMap::with_capacity(n),
}
}
}
impl<T, S> RingSet<T, S> {
pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self {
RingSet {
map: RingMap::with_capacity_and_hasher(n, hash_builder),
}
}
pub const fn with_hasher(hash_builder: S) -> Self {
RingSet {
map: RingMap::with_hasher(hash_builder),
}
}
#[inline]
pub(crate) fn into_entries(self) -> VecDeque<Bucket<T>> {
self.map.into_entries()
}
#[inline]
pub(crate) fn as_entries(&self) -> &VecDeque<Bucket<T>> {
self.map.as_entries()
}
pub(crate) fn with_contiguous_entries<F>(&mut self, f: F)
where
F: FnOnce(&mut [Bucket<T>]),
{
self.map.with_contiguous_entries(f);
}
pub fn capacity(&self) -> usize {
self.map.capacity()
}
pub fn hasher(&self) -> &S {
self.map.hasher()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn iter(&self) -> Iter<'_, T> {
Iter::new(self.as_entries())
}
pub fn clear(&mut self) {
self.map.clear();
}
pub fn truncate(&mut self, len: usize) {
self.map.truncate(len);
}
#[track_caller]
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
{
Drain::new(self.map.core.drain(range))
}
#[track_caller]
pub fn extract_if<F, R>(&mut self, range: R, pred: F) -> ExtractIf<'_, T, F>
where
F: FnMut(&T) -> bool,
R: RangeBounds<usize>,
{
ExtractIf::new(&mut self.map.core, range, pred)
}
#[track_caller]
pub fn split_off(&mut self, at: usize) -> Self
where
S: Clone,
{
Self {
map: self.map.split_off(at),
}
}
pub fn reserve(&mut self, additional: usize) {
self.map.reserve(additional);
}
pub fn reserve_exact(&mut self, additional: usize) {
self.map.reserve_exact(additional);
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.map.try_reserve(additional)
}
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.map.try_reserve_exact(additional)
}
pub fn shrink_to_fit(&mut self) {
self.map.shrink_to_fit();
}
pub fn shrink_to(&mut self, min_capacity: usize) {
self.map.shrink_to(min_capacity);
}
}
impl<T, S> RingSet<T, S>
where
T: Hash + Eq,
S: BuildHasher,
{
pub fn insert(&mut self, value: T) -> bool {
self.map.insert(value, ()).is_none()
}
#[deprecated = "use `push_back` or `push_front` instead"]
pub fn insert_full(&mut self, value: T) -> (usize, bool) {
self.push_back(value)
}
pub fn push_back(&mut self, value: T) -> (usize, bool) {
let (index, existing) = self.map.push_back(value, ());
(index, existing.is_none())
}
pub fn push_front(&mut self, value: T) -> (usize, bool) {
let (index, existing) = self.map.push_front(value, ());
(index, existing.is_none())
}
pub fn insert_sorted(&mut self, value: T) -> (usize, bool)
where
T: Ord,
{
let (index, existing) = self.map.insert_sorted(value, ());
(index, existing.is_none())
}
pub fn insert_sorted_by<F>(&mut self, value: T, mut cmp: F) -> (usize, bool)
where
F: FnMut(&T, &T) -> Ordering,
{
let (index, existing) = self
.map
.insert_sorted_by(value, (), |a, (), b, ()| cmp(a, b));
(index, existing.is_none())
}
pub fn insert_sorted_by_key<B, F>(&mut self, value: T, mut sort_key: F) -> (usize, bool)
where
B: Ord,
F: FnMut(&T) -> B,
{
let (index, existing) = self.map.insert_sorted_by_key(value, (), |k, _| sort_key(k));
(index, existing.is_none())
}
#[track_caller]
pub fn insert_before(&mut self, index: usize, value: T) -> (usize, bool) {
let (index, existing) = self.map.insert_before(index, value, ());
(index, existing.is_none())
}
#[track_caller]
pub fn shift_insert(&mut self, index: usize, value: T) -> bool {
self.map.shift_insert(index, value, ()).is_none()
}
pub fn replace(&mut self, value: T) -> Option<T> {
self.replace_full(value).1
}
pub fn replace_full(&mut self, value: T) -> (usize, Option<T>) {
let hash = self.map.hash(&value);
match self.map.core.replace_full(hash, value, ()) {
(i, Some((replaced, ()))) => (i, Some(replaced)),
(i, None) => (i, None),
}
}
#[track_caller]
pub fn replace_index(&mut self, index: usize, value: T) -> Result<T, (usize, T)> {
self.map.replace_index(index, value)
}
pub fn difference<'a, S2>(&'a self, other: &'a RingSet<T, S2>) -> Difference<'a, T, S2>
where
S2: BuildHasher,
{
Difference::new(self, other)
}
pub fn symmetric_difference<'a, S2>(
&'a self,
other: &'a RingSet<T, S2>,
) -> SymmetricDifference<'a, T, S, S2>
where
S2: BuildHasher,
{
SymmetricDifference::new(self, other)
}
pub fn intersection<'a, S2>(&'a self, other: &'a RingSet<T, S2>) -> Intersection<'a, T, S2>
where
S2: BuildHasher,
{
Intersection::new(self, other)
}
pub fn union<'a, S2>(&'a self, other: &'a RingSet<T, S2>) -> Union<'a, T, S>
where
S2: BuildHasher,
{
Union::new(self, other)
}
#[track_caller]
pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, T, S>
where
R: RangeBounds<usize>,
I: IntoIterator<Item = T>,
{
Splice::new(self, range, replace_with.into_iter())
}
pub fn append<S2>(&mut self, other: &mut RingSet<T, S2>) {
self.map.append(&mut other.map);
}
}
impl<T, S> RingSet<T, S>
where
S: BuildHasher,
{
pub fn contains<Q>(&self, value: &Q) -> bool
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.contains_key(value)
}
pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_key_value(value).map(|(x, &())| x)
}
pub fn get_full<Q>(&self, value: &Q) -> Option<(usize, &T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_full(value).map(|(i, x, &())| (i, x))
}
pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_index_of(value)
}
pub fn remove<Q>(&mut self, value: &Q) -> bool
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.remove(value).is_some()
}
pub fn take<Q>(&mut self, value: &Q) -> Option<T>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.remove_entry(value).map(|(x, ())| x)
}
pub fn remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.remove_full(value).map(|(i, x, ())| (i, x))
}
pub fn swap_remove_back<Q>(&mut self, value: &Q) -> bool
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_back(value).is_some()
}
pub fn swap_take_back<Q>(&mut self, value: &Q) -> Option<T>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_back_entry(value).map(|(x, ())| x)
}
pub fn swap_remove_back_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map
.swap_remove_back_full(value)
.map(|(i, x, ())| (i, x))
}
pub fn swap_remove_front<Q>(&mut self, value: &Q) -> bool
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_front(value).is_some()
}
pub fn swap_take_front<Q>(&mut self, value: &Q) -> Option<T>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.swap_remove_front_entry(value).map(|(x, ())| x)
}
pub fn swap_remove_front_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map
.swap_remove_front_full(value)
.map(|(i, x, ())| (i, x))
}
}
impl<T, S> RingSet<T, S> {
#[doc(alias = "pop", alias = "pop_last")] pub fn pop_back(&mut self) -> Option<T> {
self.map.pop_back().map(|(x, ())| x)
}
#[doc(alias = "pop_first")] pub fn pop_front(&mut self) -> Option<T> {
self.map.pop_front().map(|(x, ())| x)
}
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
let last = self.back()?;
if predicate(last) {
self.pop_back()
} else {
None
}
}
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&T) -> bool) -> Option<T> {
let first = self.front()?;
if predicate(first) {
self.pop_front()
} else {
None
}
}
pub fn retain<F>(&mut self, mut keep: F)
where
F: FnMut(&T) -> bool,
{
self.map.retain(move |x, &mut ()| keep(x))
}
pub fn sort(&mut self)
where
T: Ord,
{
self.map.sort_keys()
}
pub fn sort_by<F>(&mut self, mut cmp: F)
where
F: FnMut(&T, &T) -> Ordering,
{
self.map.sort_by(move |a, (), b, ()| cmp(a, b));
}
pub fn sorted_by<F>(self, mut cmp: F) -> IntoIter<T>
where
F: FnMut(&T, &T) -> Ordering,
{
let mut entries = self.into_entries();
entries
.make_contiguous()
.sort_by(move |a, b| cmp(&a.key, &b.key));
IntoIter::new(entries)
}
pub fn sort_by_key<K, F>(&mut self, mut sort_key: F)
where
K: Ord,
F: FnMut(&T) -> K,
{
self.with_contiguous_entries(move |entries| {
entries.sort_by_key(move |a| sort_key(&a.key));
});
}
pub fn sort_unstable(&mut self)
where
T: Ord,
{
self.map.sort_unstable_keys()
}
pub fn sort_unstable_by<F>(&mut self, mut cmp: F)
where
F: FnMut(&T, &T) -> Ordering,
{
self.map.sort_unstable_by(move |a, _, b, _| cmp(a, b))
}
pub fn sorted_unstable_by<F>(self, mut cmp: F) -> IntoIter<T>
where
F: FnMut(&T, &T) -> Ordering,
{
let mut entries = self.into_entries();
entries
.make_contiguous()
.sort_unstable_by(move |a, b| cmp(&a.key, &b.key));
IntoIter::new(entries)
}
pub fn sort_unstable_by_key<K, F>(&mut self, mut sort_key: F)
where
K: Ord,
F: FnMut(&T) -> K,
{
self.with_contiguous_entries(move |entries| {
entries.sort_unstable_by_key(move |a| sort_key(&a.key));
});
}
pub fn sort_by_cached_key<K, F>(&mut self, mut sort_key: F)
where
K: Ord,
F: FnMut(&T) -> K,
{
self.with_contiguous_entries(move |entries| {
entries.sort_by_cached_key(move |a| sort_key(&a.key));
});
}
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
where
T: Ord,
{
self.map.binary_search_keys(x)
}
#[inline]
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> Ordering,
{
self.map.binary_search_by(move |key, ()| f(key))
}
#[inline]
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
where
F: FnMut(&'a T) -> B,
B: Ord,
{
self.map.binary_search_by_key(b, move |key, ()| f(key))
}
#[inline]
pub fn is_sorted(&self) -> bool
where
T: PartialOrd,
{
self.iter().is_sorted()
}
#[inline]
pub fn is_sorted_by<'a, F>(&'a self, mut cmp: F) -> bool
where
F: FnMut(&'a T, &'a T) -> bool,
{
self.iter().is_sorted_by(|&v1, &v2| cmp(v1, v2))
}
#[inline]
pub fn is_sorted_by_key<'a, F, K>(&'a self, sort_key: F) -> bool
where
F: FnMut(&'a T) -> K,
K: PartialOrd,
{
self.iter().is_sorted_by_key(sort_key)
}
#[must_use]
pub fn partition_point<P>(&self, mut pred: P) -> usize
where
P: FnMut(&T) -> bool,
{
self.map.partition_point(move |key, ()| pred(key))
}
pub fn reverse(&mut self) {
self.map.reverse()
}
pub fn as_slices(&self) -> (&Slice<T>, &Slice<T>) {
let (head, tail) = self.as_entries().as_slices();
(Slice::from_slice(head), Slice::from_slice(tail))
}
pub fn make_contiguous(&mut self) -> &Slice<T> {
Slice::from_slice(self.map.as_entries_mut().make_contiguous())
}
pub fn into_boxed_slice(self) -> Box<Slice<T>> {
let entries = Vec::from(self.into_entries());
Slice::from_boxed(entries.into_boxed_slice())
}
pub fn get_index(&self, index: usize) -> Option<&T> {
self.as_entries().get(index).map(Bucket::key_ref)
}
#[track_caller]
pub fn range<R>(&self, range: R) -> Iter<'_, T>
where
R: RangeBounds<usize>,
{
let (head_range, tail_range) = self.map.split_range(range);
let (head, tail) = self.as_entries().as_slices();
Iter::from_slices(&head[head_range], &tail[tail_range])
}
pub fn get_range<R>(&self, range: R) -> Option<(&Slice<T>, &Slice<T>)>
where
R: RangeBounds<usize>,
{
let (head_range, tail_range) = self.map.try_split_range(range)?;
let (head, tail) = self.as_entries().as_slices();
Some((
Slice::from_slice(&head[head_range]),
Slice::from_slice(&tail[tail_range]),
))
}
#[doc(alias = "first")] pub fn front(&self) -> Option<&T> {
self.as_entries().get(0).map(Bucket::key_ref)
}
#[doc(alias = "last")] pub fn back(&self) -> Option<&T> {
let i = self.len().checked_sub(1)?;
self.as_entries().get(i).map(Bucket::key_ref)
}
pub fn swap_remove_back_index(&mut self, index: usize) -> Option<T> {
self.map.swap_remove_back_index(index).map(|(x, ())| x)
}
pub fn swap_remove_front_index(&mut self, index: usize) -> Option<T> {
self.map.swap_remove_front_index(index).map(|(x, ())| x)
}
pub fn remove_index(&mut self, index: usize) -> Option<T> {
self.map.remove_index(index).map(|(x, ())| x)
}
#[track_caller]
pub fn move_index(&mut self, from: usize, to: usize) {
self.map.move_index(from, to)
}
#[track_caller]
pub fn swap_indices(&mut self, a: usize, b: usize) {
self.map.swap_indices(a, b)
}
}
impl<T, S> Index<usize> for RingSet<T, S> {
type Output = T;
fn index(&self, index: usize) -> &T {
if let Some(value) = self.get_index(index) {
value
} else {
panic!(
"index out of bounds: the len is {len} but the index is {index}",
len = self.len()
);
}
}
}
impl<T, S> FromIterator<T> for RingSet<T, S>
where
T: Hash + Eq,
S: BuildHasher + Default,
{
fn from_iter<I: IntoIterator<Item = T>>(iterable: I) -> Self {
let iter = iterable.into_iter().map(|x| (x, ()));
RingSet {
map: RingMap::from_iter(iter),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T, const N: usize> From<[T; N]> for RingSet<T, RandomState>
where
T: Eq + Hash,
{
fn from(arr: [T; N]) -> Self {
Self::from_iter(arr)
}
}
impl<T, S> Extend<T> for RingSet<T, S>
where
T: Hash + Eq,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iterable: I) {
let iter = iterable.into_iter().map(|x| (x, ()));
self.map.extend(iter);
}
}
impl<'a, T, S> Extend<&'a T> for RingSet<T, S>
where
T: Hash + Eq + Copy + 'a,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iterable: I) {
let iter = iterable.into_iter().copied();
self.extend(iter);
}
}
impl<T, S> Default for RingSet<T, S>
where
S: Default,
{
fn default() -> Self {
RingSet {
map: RingMap::default(),
}
}
}
impl<T, S1, S2> PartialEq<RingSet<T, S2>> for RingSet<T, S1>
where
T: PartialEq,
{
fn eq(&self, other: &RingSet<T, S2>) -> bool {
self.len() == other.len() && self.iter().eq(other)
}
}
impl<T, S> Eq for RingSet<T, S> where T: Eq {}
impl<T, S1, S2> PartialOrd<RingSet<T, S2>> for RingSet<T, S1>
where
T: PartialOrd,
{
fn partial_cmp(&self, other: &RingSet<T, S2>) -> Option<Ordering> {
self.iter().partial_cmp(other)
}
}
impl<T, S> Ord for RingSet<T, S>
where
T: Ord,
{
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other)
}
}
impl<T, S> Hash for RingSet<T, S>
where
T: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
for value in self {
value.hash(state);
}
}
}
impl<T, S> RingSet<T, S>
where
T: Eq + Hash,
S: BuildHasher,
{
pub fn is_disjoint<S2>(&self, other: &RingSet<T, S2>) -> bool
where
S2: BuildHasher,
{
if self.len() <= other.len() {
self.iter().all(move |value| !other.contains(value))
} else {
other.iter().all(move |value| !self.contains(value))
}
}
pub fn is_subset<S2>(&self, other: &RingSet<T, S2>) -> bool
where
S2: BuildHasher,
{
self.len() <= other.len() && self.iter().all(move |value| other.contains(value))
}
pub fn is_superset<S2>(&self, other: &RingSet<T, S2>) -> bool
where
S2: BuildHasher,
{
other.is_subset(self)
}
pub fn set_eq<S2>(&self, other: &RingSet<T, S2>) -> bool
where
S2: BuildHasher,
{
self.len() == other.len() && self.is_subset(other)
}
}
impl<T, S1, S2> BitAnd<&RingSet<T, S2>> for &RingSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = RingSet<T, S1>;
fn bitand(self, other: &RingSet<T, S2>) -> Self::Output {
self.intersection(other).cloned().collect()
}
}
impl<T, S1, S2> BitOr<&RingSet<T, S2>> for &RingSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = RingSet<T, S1>;
fn bitor(self, other: &RingSet<T, S2>) -> Self::Output {
self.union(other).cloned().collect()
}
}
impl<T, S1, S2> BitXor<&RingSet<T, S2>> for &RingSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = RingSet<T, S1>;
fn bitxor(self, other: &RingSet<T, S2>) -> Self::Output {
self.symmetric_difference(other).cloned().collect()
}
}
impl<T, S1, S2> Sub<&RingSet<T, S2>> for &RingSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = RingSet<T, S1>;
fn sub(self, other: &RingSet<T, S2>) -> Self::Output {
self.difference(other).cloned().collect()
}
}