diff --git a/Cargo.toml b/Cargo.toml index f8447be..d052ac5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ serde = "1.0" unreachable = "1.0" [dev-dependencies] -criterion = { git = "https://github.com/japaric/criterion.rs.git" } +criterion = "0.1" rand = "0.4" serde_test = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 07c8b57..1ca026e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -246,6 +246,27 @@ impl<'a> ops::BitOr<&'a Self> for BitSet { } } +impl<'a> ops::Sub<&'a BitSet> for &'a BitSet { + type Output = BitSet; + + #[inline] + fn sub(self, rhs: &'a BitSet) -> BitSet { + let mut set = self.clone(); + + set.nbits = 0; + + for (key, value) in &rhs.blocks { + let block = set.blocks.entry(*key).or_insert(0); + + *block = !value & *block; + + set.nbits += block.count_ones() as usize; + } + + set + } +} + pub struct Iter<'a> { iter: std::collections::hash_map::Iter<'a, u64, u64>, block: u64, @@ -548,6 +569,22 @@ mod tests { assert_eq!(observed, 0xFFFF_FFFF); } + #[test] + fn test_sub() { + let a: BitSet = vec![1, 2, 3].into_iter().collect(); + let b: BitSet = vec![3, 4, 5].into_iter().collect(); + + let set = &a - &b; + + let mut i = 0; + let expected = [1, 2]; + for x in &set { + assert!(expected.contains(&x)); + i += 1; + } + assert_eq!(i, expected.len()); + } + #[test] fn test_from_iter() { let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];