summaryrefslogtreecommitdiffstats
path: root/vendor/tinyvec/src-backup/arrayset.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/tinyvec/src-backup/arrayset.rs')
-rw-r--r--vendor/tinyvec/src-backup/arrayset.rs303
1 files changed, 303 insertions, 0 deletions
diff --git a/vendor/tinyvec/src-backup/arrayset.rs b/vendor/tinyvec/src-backup/arrayset.rs
new file mode 100644
index 000000000..22ea7cae9
--- /dev/null
+++ b/vendor/tinyvec/src-backup/arrayset.rs
@@ -0,0 +1,303 @@
+#![cfg(feature = "experimental_array_set")]
+
+// This was contributed by user `dhardy`! Big thanks.
+
+use super::{take, Array};
+use core::{
+ borrow::Borrow,
+ fmt,
+ mem::swap,
+ ops::{AddAssign, SubAssign},
+};
+
+/// Error resulting from attempting to insert into a full array
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct InsertError;
+
+// TODO(when std): impl std::error::Error for InsertError {}
+
+impl fmt::Display for InsertError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "ArraySet: insertion failed")
+ }
+}
+
+/// An array-backed set
+///
+/// This set supports `O(n)` operations and has a fixed size, thus may fail to
+/// insert items. The potential advantage is a *really* small size.
+///
+/// The set is backed by an array of type `A` and indexed by type `L`.
+/// The item type must support `Default`.
+/// Due to restrictions, `L` may be only `u8` or `u16`.
+#[derive(Clone, Debug, Default)]
+pub struct ArraySet<A: Array, L> {
+ arr: A,
+ len: L,
+}
+
+impl<A: Array + Default, L: From<u8>> ArraySet<A, L> {
+ /// Constructs a new, empty, set
+ #[inline]
+ pub fn new() -> Self {
+ ArraySet { arr: Default::default(), len: 0.into() }
+ }
+}
+
+impl<A: Array, L: Copy + Into<usize>> ArraySet<A, L> {
+ /// Constructs a new set from given inputs
+ ///
+ /// Panics if `len> arr.len()`.
+ #[inline]
+ pub fn from(arr: A, len: L) -> Self {
+ if len.into() > A::CAPACITY {
+ panic!("ArraySet::from(array, len): len > array.len()");
+ }
+ ArraySet { arr, len }
+ }
+}
+
+impl<A: Array, L> ArraySet<A, L>
+where
+ L: Copy + PartialEq + From<u8> + Into<usize>,
+{
+ /// Returns the fixed capacity of the set
+ #[inline]
+ pub fn capacity(&self) -> usize {
+ A::CAPACITY
+ }
+
+ /// Returns the number of elements in the set
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.len.into()
+ }
+
+ /// Returns true when the set contains no elements
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.len == 0.into()
+ }
+
+ /// Removes all elements
+ #[inline]
+ pub fn clear(&mut self) {
+ self.len = 0.into();
+ }
+
+ /// Iterate over all contents
+ #[inline]
+ pub fn iter(&self) -> Iter<A::Item> {
+ Iter { a: self.arr.as_slice(), i: 0 }
+ }
+}
+
+impl<A: Array, L> ArraySet<A, L>
+where
+ L: Copy + PartialOrd + AddAssign + SubAssign + From<u8> + Into<usize>,
+{
+ /// Check whether the set contains `elt`
+ #[inline]
+ pub fn contains<Q: Eq + ?Sized>(&self, elt: &Q) -> bool
+ where
+ A::Item: Borrow<Q>,
+ {
+ self.get(elt).is_some()
+ }
+
+ /// Get a reference to a contained item matching `elt`
+ pub fn get<Q: Eq + ?Sized>(&self, elt: &Q) -> Option<&A::Item>
+ where
+ A::Item: Borrow<Q>,
+ {
+ let len: usize = self.len.into();
+ let arr = self.arr.as_slice();
+ for i in 0..len {
+ if arr[i].borrow() == elt {
+ return Some(&arr[i]);
+ }
+ }
+ None
+ }
+
+ /// Remove an item matching `elt`, if any
+ pub fn remove<Q: Eq + ?Sized>(&mut self, elt: &Q) -> Option<A::Item>
+ where
+ A::Item: Borrow<Q>,
+ {
+ let len: usize = self.len.into();
+ let arr = self.arr.as_slice_mut();
+ for i in 0..len {
+ if arr[i].borrow() == elt {
+ let l1 = len - 1;
+ if i < l1 {
+ arr.swap(i, l1);
+ }
+ self.len -= L::from(1);
+ return Some(take(&mut arr[l1]));
+ }
+ }
+ None
+ }
+
+ /// Remove any items for which `f(item) == false`
+ pub fn retain<F>(&mut self, mut f: F)
+ where
+ F: FnMut(&A::Item) -> bool,
+ {
+ let mut len = self.len;
+ let arr = self.arr.as_slice_mut();
+ let mut i = 0;
+ while i < len.into() {
+ if !f(&arr[i]) {
+ len -= L::from(1);
+ if i < len.into() {
+ arr.swap(i, len.into());
+ }
+ } else {
+ i += 1;
+ }
+ }
+ self.len = len;
+ }
+}
+
+impl<A: Array, L> ArraySet<A, L>
+where
+ A::Item: Eq,
+ L: Copy + PartialOrd + AddAssign + SubAssign + From<u8> + Into<usize>,
+{
+ /// Insert an item
+ ///
+ /// Due to the fixed size of the backing array, insertion may fail.
+ #[inline]
+ pub fn insert(&mut self, elt: A::Item) -> Result<bool, InsertError> {
+ if self.contains(&elt) {
+ return Ok(false);
+ }
+
+ let len = self.len.into();
+ let arr = self.arr.as_slice_mut();
+ if len >= arr.len() {
+ return Err(InsertError);
+ }
+ arr[len] = elt;
+ self.len += L::from(1);
+ Ok(true)
+ }
+
+ /* Hits borrow checker
+ pub fn get_or_insert(&mut self, elt: A::Item) -> Result<&A::Item, InsertError> {
+ if let Some(r) = self.get(&elt) {
+ return Ok(r);
+ }
+ self.insert(elt)?;
+ let len: usize = self.len.into();
+ Ok(&self.arr.as_slice()[len - 1])
+ }
+ */
+
+ /// Replace an item matching `elt` with `elt`, or insert `elt`
+ ///
+ /// Returns the replaced item, if any. Fails when there is no matching item
+ /// and the backing array is full, preventing insertion.
+ pub fn replace(
+ &mut self,
+ mut elt: A::Item,
+ ) -> Result<Option<A::Item>, InsertError> {
+ let len: usize = self.len.into();
+ let arr = self.arr.as_slice_mut();
+ for i in 0..len {
+ if arr[i] == elt {
+ swap(&mut arr[i], &mut elt);
+ return Ok(Some(elt));
+ }
+ }
+
+ if len >= arr.len() {
+ return Err(InsertError);
+ }
+ arr[len] = elt;
+ self.len += L::from(1);
+ Ok(None)
+ }
+}
+
+/// Type returned by [`ArraySet::iter`]
+pub struct Iter<'a, T> {
+ a: &'a [T],
+ i: usize,
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ #[inline]
+ fn len(&self) -> usize {
+ self.a.len() - self.i
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.i < self.a.len() {
+ let i = self.i;
+ self.i += 1;
+ Some(&self.a[i])
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.len();
+ (len, Some(len))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use core::mem::size_of;
+
+ #[test]
+ fn test_size() {
+ assert_eq!(size_of::<ArraySet<[i8; 7], u8>>(), 8);
+ }
+
+ #[test]
+ fn test() {
+ let mut set: ArraySet<[i8; 7], u8> = ArraySet::new();
+ assert_eq!(set.capacity(), 7);
+
+ assert_eq!(set.insert(1), Ok(true));
+ assert_eq!(set.insert(5), Ok(true));
+ assert_eq!(set.insert(6), Ok(true));
+ assert_eq!(set.len(), 3);
+
+ assert_eq!(set.insert(5), Ok(false));
+ assert_eq!(set.len(), 3);
+
+ assert_eq!(set.replace(1), Ok(Some(1)));
+ assert_eq!(set.replace(2), Ok(None));
+ assert_eq!(set.len(), 4);
+
+ assert_eq!(set.insert(3), Ok(true));
+ assert_eq!(set.insert(4), Ok(true));
+ assert_eq!(set.insert(7), Ok(true));
+ assert_eq!(set.insert(8), Err(InsertError));
+ assert_eq!(set.len(), 7);
+
+ assert_eq!(set.replace(9), Err(InsertError));
+
+ assert_eq!(set.remove(&3), Some(3));
+ assert_eq!(set.len(), 6);
+
+ set.retain(|x| *x == 3 || *x == 6);
+ assert_eq!(set.len(), 1);
+ assert!(!set.contains(&3));
+ assert!(set.contains(&6));
+ }
+}