tinyset 0.5.3

Size-optimized sets
Documentation
#[cfg(test)]
pub trait CopySet: Default + Clone {
    type Item: Copy + Eq + Ord + std::fmt::Display + std::fmt::Debug;
    type Iter: Iterator<Item = Self::Item>;
    fn ins(&mut self, e: Self::Item) -> bool;
    fn rem(&mut self, e: Self::Item) -> bool;
    fn con(&self, e: Self::Item) -> bool;
    fn vec(&self) -> Vec<Self::Item>;
    fn ln(&self) -> usize;
    fn it(self) -> Self::Iter;
}

macro_rules! impl_set_methods {
    ($ty: ty) => {
impl PartialEq for $ty {
    fn eq(&self, other: &Self) -> bool {
        if self.len() != other.len() {
            return false;
        }
        for i in self.iter() {
            if !other.contains(i) {
                return false;
            }
        }
        true
    }
}
impl Eq for $ty {}

impl std::fmt::Debug for $ty {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, concat!(stringify!($ty), " {:?}"), self.iter().collect::<Vec<_>>())?;
        Ok(())
    }
}

impl<'a, 'b> std::ops::Sub<&'b $ty> for &'a $ty {
    type Output = $ty;
    #[doc = concat!(
        "Returns the difference of `self` and `rhs` as a new `", stringify!($ty), "`.

# Examples

```
let a: tinyset::",  stringify!($ty), " = (1..4).collect();
let b: tinyset::",  stringify!($ty), " = (3..6).into_iter().collect();

assert_eq!(&a - &b, (1..3).collect());
```
"
    )]
    fn sub(self, rhs: &$ty) -> $ty {
        let mut s = <$ty>::with_capacity_of(&self);
        for v in self.iter() {
            if !rhs.contains(v) {
                s.insert(v);
            }
        }
        s
    }
}

impl<'b> std::ops::Sub<&'b $ty> for $ty {
    type Output = $ty;
    #[doc = concat!(
        "Returns the difference of `self` and `rhs` as a new `", stringify!($ty), "` consuming `self`.  Should not allocate.

# Examples

```
let a: tinyset::",  stringify!($ty), " = (1..4).collect();
let b: tinyset::",  stringify!($ty), " = (3..6).into_iter().collect();

assert_eq!(a - &b, (1..3).collect());
```
"
    )]
    fn sub(mut self, rhs: &$ty) -> $ty {
        for v in rhs.iter() {
            self.remove(v);
        }
        self
    }
}

impl<'a, 'b> std::ops::BitOr<&'b $ty> for &'a $ty {
    type Output = $ty;
    #[doc = concat!(
        "Returns the union of `self` and `rhs` as a new `", stringify!($ty), "`.

# Examples

```
let a: tinyset::",  stringify!($ty), " = (1..4).collect();
let b: tinyset::",  stringify!($ty), " = (3..6).collect();

assert_eq!(&a | &b, (1..6).collect());
```
"
    )]
    fn bitor(self, rhs: & $ty) -> $ty {
        let mut s: $ty = if self.len() > rhs.len() {
            <$ty>::with_capacity_of(&self)
        } else {
            <$ty>::with_capacity_of(&rhs)
        };
        for x in self.iter() {
            s.insert(x);
        }
        for x in rhs.iter() {
            s.insert(x);
        }
        s
    }
}

impl<'b> std::ops::BitOr<&'b $ty> for $ty {
    type Output = $ty;
    #[doc = concat!(
        "Returns the union of `self` and `rhs` as a new `", stringify!($ty), "`, consuming `self`.

# Examples

```
let a: tinyset::",  stringify!($ty), " = (1..4).collect();
let b: tinyset::",  stringify!($ty), " = (3..6).collect();

assert_eq!(a | &b, (1..6).collect());
```
"
    )]
    fn bitor(mut self, rhs: & $ty) -> $ty {
        for x in rhs.iter() {
            self.insert(x);
        }
        self
    }
}

}
}

pub(crate) use impl_set_methods;

#[cfg(test)]
impl CopySet for std::collections::HashSet<u64> {
    type Item = u64;
    type Iter = std::collections::hash_set::IntoIter<u64>;
    fn ins(&mut self, e: u64) -> bool {
        self.insert(e)
    }
    fn rem(&mut self, e: u64) -> bool {
        self.remove(&e)
    }
    fn con(&self, e: u64) -> bool {
        self.contains(&e)
    }
    fn vec(&self) -> Vec<u64> {
        self.iter().cloned().collect()
    }
    fn ln(&self) -> usize {
        self.len()
    }
    fn it(self) -> Self::Iter {
        self.into_iter()
    }
}

#[cfg(test)]
impl CopySet for std::collections::HashSet<u32> {
    type Item = u32;
    type Iter = std::collections::hash_set::IntoIter<u32>;
    fn ins(&mut self, e: u32) -> bool {
        self.insert(e)
    }
    fn rem(&mut self, e: u32) -> bool {
        self.remove(&e)
    }
    fn con(&self, e: u32) -> bool {
        self.contains(&e)
    }
    fn vec(&self) -> Vec<u32> {
        self.iter().cloned().collect()
    }
    fn ln(&self) -> usize {
        self.len()
    }
    fn it(self) -> Self::Iter {
        self.into_iter()
    }
}

#[cfg(test)]
use proptest::prelude::*;
#[cfg(test)]
proptest! {
    #[test]
    fn check_random_sets(slice in prop::collection::vec(1u64..5, 1usize..10)) {
        check_set::<std::collections::HashSet<u64>>(&slice);
    }
    #[test]
    fn check_medium_sets(slice in prop::collection::vec(1u64..255, 1usize..100)) {
        check_set::<std::collections::HashSet<u64>>(&slice);
    }
    #[test]
    fn check_big_sets(slice: Vec<u64>) {
        check_set::<std::collections::HashSet<u64>>(&slice);
    }
}

#[cfg(test)]
pub fn check_set<T: CopySet>(elems: &[T::Item]) {
    println!("\n\ncheck_set {:?}\n", elems);
    let mut s = T::default();
    let mut count = 0;
    for x in elems.iter().cloned() {
        let was_here = s.con(x);
        let changed_something = s.ins(x);
        if changed_something {
            count += 1;
            println!("    {} is new now count {}", x, count);
        }
        assert_eq!(!was_here, changed_something);
        println!("what is this? count {} does it have {}?", count, x);
        assert!(s.con(x));
        assert_eq!(s.ln(), count);
        assert_eq!(s.vec().into_iter().count(), count);
    }
    assert!(elems.len() >= s.ln());
    assert_eq!(elems.iter().cloned().min(), s.vec().into_iter().min());
    println!("set {:?} with length {}", elems, s.ln());
    for x in s.vec().into_iter() {
        println!("    {}", x);
    }
    assert_eq!(s.vec().into_iter().count(), s.ln());
    for x in s.vec().into_iter() {
        println!("looking for {}", x);
        assert!(elems.contains(&x));
    }
    for x in s.vec().into_iter() {
        println!("found {}", x);
        assert!(elems.contains(&x));
    }
    for x in s.clone().it() {
        println!("found {}", x);
        assert!(elems.contains(&x));
    }
    println!("checking max");
    assert_eq!(s.clone().it().max(), elems.iter().cloned().max());
    println!("checking min");
    assert_eq!(s.clone().it().min(), elems.iter().cloned().min());
    for x in elems.iter().cloned() {
        println!("YYYY looking for {}", x);
        assert!(s.con(x));
    }
    for x in elems.iter().cloned() {
        println!("removing {}", x);
        s.rem(x);
    }
    for x in elems.iter().cloned() {
        println!("XXXX looking for {}", x);
        assert!(!s.con(x));
    }
    assert_eq!(s.ln(), 0);
}