From cae0605b9e2857427c8519ad5f16ab624223631d Mon Sep 17 00:00:00 2001 From: Luiz Irber Date: Tue, 14 Apr 2020 15:10:16 -0700 Subject: [PATCH 1/4] add new constructor with blocks --- src/lib.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 368eccf..c3425ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,6 +67,18 @@ impl FixedBitSet length: bits, } } + /// Create a new **FixedBitSet** with a specific number of bits, + /// all initially clear. + pub fn with_capacity_and_blocks(bits: usize, data: Vec) -> Self + { + let (mut blocks, rem) = div_rem(bits, BITS); + blocks += (rem > 0) as usize; + assert_eq!(blocks, data.len()); + FixedBitSet { + data: data, + length: bits, + } + } /// Grow capacity to **bits**, all new bits initialized to zero pub fn grow(&mut self, bits: usize) { let (mut blocks, rem) = div_rem(bits, BITS); @@ -705,6 +717,14 @@ fn it_works() { fb.clear(); } +#[test] +fn with_blocks() { + let fb = FixedBitSet::with_capacity_and_blocks(50, vec![8u32, 0u32]); + + let ones: Vec<_> = fb.ones().collect(); + assert!(fb.contains(3)); +} + #[test] fn grow() { let mut fb = FixedBitSet::with_capacity(48); From 57f46223d95b5842afbbb04148b23ff71db13680 Mon Sep 17 00:00:00 2001 From: Luiz Irber Date: Wed, 15 Apr 2020 09:03:08 -0700 Subject: [PATCH 2/4] IntoIterator and more docs --- src/lib.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c3425ca..4cf20e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,12 +68,16 @@ impl FixedBitSet } } /// Create a new **FixedBitSet** with a specific number of bits, - /// all initially clear. - pub fn with_capacity_and_blocks(bits: usize, data: Vec) -> Self + /// initialized from provided blocks. + /// + /// This will panic if the blocks are not the exact size needed + /// for the capacity. + pub fn with_capacity_and_blocks>(bits: usize, blocks: I) -> Self { - let (mut blocks, rem) = div_rem(bits, BITS); - blocks += (rem > 0) as usize; - assert_eq!(blocks, data.len()); + let (mut n_blocks, rem) = div_rem(bits, BITS); + n_blocks += (rem > 0) as usize; + let data: Vec = blocks.into_iter().collect(); + assert_eq!(n_blocks, data.len()); FixedBitSet { data: data, length: bits, @@ -725,6 +729,18 @@ fn with_blocks() { assert!(fb.contains(3)); } +#[should_panic] +#[test] +fn with_blocks_too_small() { + let fb = FixedBitSet::with_capacity_and_blocks(500, vec![8u32, 0u32]); +} + +#[should_panic] +#[test] +fn with_blocks_too_big() { + let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8u32, 24u32]); +} + #[test] fn grow() { let mut fb = FixedBitSet::with_capacity(48); From d2f5fbdff8ac4472258ec8ce1b994343dbe13f41 Mon Sep 17 00:00:00 2001 From: Luiz Irber Date: Wed, 15 Apr 2020 13:15:40 -0700 Subject: [PATCH 3/4] avoid panic --- src/lib.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4cf20e3..e05861d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,14 +70,18 @@ impl FixedBitSet /// Create a new **FixedBitSet** with a specific number of bits, /// initialized from provided blocks. /// - /// This will panic if the blocks are not the exact size needed - /// for the capacity. + /// If the blocks are not the exact size needed for the capacity + /// they will be padded with zeros (if shorter) or truncated to + /// the capacity (if longer). pub fn with_capacity_and_blocks>(bits: usize, blocks: I) -> Self { let (mut n_blocks, rem) = div_rem(bits, BITS); n_blocks += (rem > 0) as usize; - let data: Vec = blocks.into_iter().collect(); - assert_eq!(n_blocks, data.len()); + let mut data: Vec = blocks.into_iter().collect(); + if data.len() != n_blocks { + data.resize(n_blocks, 0); + } + // TODO: reset any bits larger than capacity FixedBitSet { data: data, length: bits, @@ -724,21 +728,25 @@ fn it_works() { #[test] fn with_blocks() { let fb = FixedBitSet::with_capacity_and_blocks(50, vec![8u32, 0u32]); + assert!(fb.contains(3)); let ones: Vec<_> = fb.ones().collect(); - assert!(fb.contains(3)); + assert_eq!(ones.len(), 1); } -#[should_panic] #[test] fn with_blocks_too_small() { - let fb = FixedBitSet::with_capacity_and_blocks(500, vec![8u32, 0u32]); + let mut fb = FixedBitSet::with_capacity_and_blocks(500, vec![8u32, 0u32]); + fb.insert(400); + assert!(fb.contains(400)); } -#[should_panic] #[test] fn with_blocks_too_big() { let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8u32, 24u32]); + + // since capacity is 1, 3 shouldn't be set here + assert!(!fb.contains(3)); } #[test] From 3cea79e8ddd1ee960df8d29c49aa9bcec266eeab Mon Sep 17 00:00:00 2001 From: Luiz Irber Date: Wed, 15 Apr 2020 15:51:29 -0700 Subject: [PATCH 4/4] disable bits past capacity --- src/lib.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e05861d..3f952aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,15 +78,23 @@ impl FixedBitSet let (mut n_blocks, rem) = div_rem(bits, BITS); n_blocks += (rem > 0) as usize; let mut data: Vec = blocks.into_iter().collect(); + // Pad data with zeros if smaller or truncate if larger if data.len() != n_blocks { data.resize(n_blocks, 0); } - // TODO: reset any bits larger than capacity + // Disable bits in blocks beyond capacity + let end = data.len() * 32; + for (block, mask) in Masks::new(bits..end, end) { + unsafe { + *data.get_unchecked_mut(block) &= !mask; + } + } FixedBitSet { data: data, length: bits, } } + /// Grow capacity to **bits**, all new bits initialized to zero pub fn grow(&mut self, bits: usize) { let (mut blocks, rem) = div_rem(bits, BITS); @@ -743,12 +751,23 @@ fn with_blocks_too_small() { #[test] fn with_blocks_too_big() { - let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8u32, 24u32]); + let fb = FixedBitSet::with_capacity_and_blocks(1, vec![8u32]); // since capacity is 1, 3 shouldn't be set here assert!(!fb.contains(3)); } +#[test] +fn with_blocks_too_big_range_check() { + let fb = FixedBitSet::with_capacity_and_blocks(1, vec![0xff]); + + // since capacity is 1, only 0 should be set + assert!(fb.contains(0)); + for i in 1..0xff { + assert!(!fb.contains(i)); + } +} + #[test] fn grow() { let mut fb = FixedBitSet::with_capacity(48);