Skip to content

Commit 75ddc13

Browse files
authored
fix: bug in bitset unset function (#16)
* fix: bug in bitset unset function * fix: clippy warnings * add: clippy check on CI
1 parent 4a03e84 commit 75ddc13

File tree

3 files changed

+252
-2
lines changed

3 files changed

+252
-2
lines changed

.github/workflows/rust.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ jobs:
1616

1717
steps:
1818
- uses: actions/checkout@v3
19+
- name: Clippy
20+
run: cargo clippy -- -D warnings
1921
- name: Build
2022
run: cargo build --release --verbose
2123
- name: Run tests

poppy/src/bitset/array.rs

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
12
/// Array based bitset implementation.
23
/// N gives the size in Bytes of the bucket
34
#[derive(Debug, Clone)]
45
pub struct BitSet<const N: usize>([u8; N]);
56

7+
impl<const N: usize> Default for BitSet<N> {
8+
fn default() -> Self {
9+
Self([0u8; N])
10+
}
11+
}
12+
613
impl<const N: usize> BitSet<N> {
714
/// Creates a new bitset
815
pub const fn new() -> Self {
@@ -15,7 +22,11 @@ impl<const N: usize> BitSet<N> {
1522
// equivalent to index % 8
1623
let mask = (value as u8) << (index & 7);
1724
let old = self.0[iblock] & mask == mask;
18-
self.0[iblock] |= mask;
25+
if value {
26+
self.0[iblock] |= mask;
27+
} else {
28+
self.0[iblock] &= mask;
29+
}
1930
old
2031
}
2132

@@ -131,3 +142,131 @@ impl<const N: usize> BitSet<N> {
131142
N * 8
132143
}
133144
}
145+
146+
#[cfg(test)]
147+
mod tests {
148+
use super::*;
149+
150+
#[test]
151+
fn test_new_bitset() {
152+
let bitset: BitSet<2> = BitSet::new();
153+
assert_eq!(bitset.as_slice(), &[0u8; 2]);
154+
}
155+
156+
#[test]
157+
fn test_default_bitset() {
158+
let bitset: BitSet<2> = BitSet::default();
159+
assert_eq!(bitset.as_slice(), &[0u8; 2]);
160+
}
161+
162+
#[test]
163+
fn test_set_nth_bit() {
164+
let mut bitset: BitSet<2> = BitSet::new();
165+
assert!(!bitset.set_nth_bit(0)); // Bit was 0, now set to 1
166+
assert!(bitset.get_nth_bit(0));
167+
}
168+
169+
#[test]
170+
fn test_unset_nth_bit() {
171+
let mut bitset: BitSet<2> = BitSet::new();
172+
bitset.set_nth_bit(0); // Set bit to 1 first
173+
assert!(bitset.unset_nth_bit(0)); // Bit was 1, now set to 0
174+
assert!(!bitset.get_nth_bit(0));
175+
}
176+
177+
#[test]
178+
fn test_get_nth_bit() {
179+
let mut bitset: BitSet<2> = BitSet::new();
180+
bitset.set_nth_bit(0);
181+
assert!(bitset.get_nth_bit(0));
182+
assert!(!bitset.get_nth_bit(1));
183+
}
184+
185+
#[test]
186+
#[should_panic(expected = "index out of bounds")]
187+
fn test_set_nth_bit_out_of_bounds() {
188+
let mut bitset: BitSet<2> = BitSet::new();
189+
bitset.set_nth_bit(16); // Assuming N=2, so 16 bits is out of bounds
190+
}
191+
192+
#[test]
193+
fn test_clear() {
194+
let mut bitset: BitSet<2> = BitSet::new();
195+
bitset.set_nth_bit(0);
196+
bitset.set_nth_bit(1);
197+
bitset.clear();
198+
assert_eq!(bitset.as_slice(), &[0u8; 2]);
199+
}
200+
201+
#[test]
202+
fn test_count_ones() {
203+
let mut bitset: BitSet<2> = BitSet::new();
204+
assert_eq!(bitset.count_ones(), 0);
205+
bitset.set_nth_bit(0);
206+
bitset.set_nth_bit(1);
207+
assert_eq!(bitset.count_ones(), 2);
208+
}
209+
210+
#[test]
211+
fn test_count_zeros() {
212+
let mut bitset: BitSet<2> = BitSet::new();
213+
assert_eq!(bitset.count_zeros(), 16); // 2 bytes = 16 bits, all zeros initially
214+
bitset.set_nth_bit(0);
215+
assert_eq!(bitset.count_zeros(), 15);
216+
}
217+
218+
#[test]
219+
fn test_union() {
220+
let mut bitset1: BitSet<2> = BitSet::new();
221+
let mut bitset2: BitSet<2> = BitSet::new();
222+
bitset1.set_nth_bit(0);
223+
bitset2.set_nth_bit(1);
224+
bitset1.union(&bitset2);
225+
assert!(bitset1.get_nth_bit(0));
226+
assert!(bitset1.get_nth_bit(1));
227+
}
228+
229+
#[test]
230+
fn test_intersection() {
231+
let mut bitset1: BitSet<2> = BitSet::new();
232+
let mut bitset2: BitSet<2> = BitSet::new();
233+
bitset1.set_nth_bit(0);
234+
bitset1.set_nth_bit(1);
235+
bitset2.set_nth_bit(1);
236+
bitset1.intersection(&bitset2);
237+
assert!(!bitset1.get_nth_bit(0));
238+
assert!(bitset1.get_nth_bit(1));
239+
}
240+
241+
#[test]
242+
fn test_count_ones_in_common() {
243+
let mut bitset1: BitSet<2> = BitSet::new();
244+
let mut bitset2: BitSet<2> = BitSet::new();
245+
bitset1.set_nth_bit(0);
246+
bitset1.set_nth_bit(1);
247+
bitset2.set_nth_bit(1);
248+
assert_eq!(bitset1.count_ones_in_common(&bitset2), 1);
249+
}
250+
251+
#[test]
252+
fn test_bit_len() {
253+
let bitset: BitSet<2> = BitSet::new();
254+
assert_eq!(bitset.bit_len(), 16); // 2 bytes = 16 bits
255+
}
256+
257+
#[test]
258+
fn test_byte_len() {
259+
let bitset: BitSet<2> = BitSet::new();
260+
assert_eq!(bitset.byte_len(), 2);
261+
}
262+
263+
#[test]
264+
fn test_byte_size() {
265+
assert_eq!(BitSet::<2>::byte_size(), 2);
266+
}
267+
268+
#[test]
269+
fn test_bit_size() {
270+
assert_eq!(BitSet::<2>::bit_size(), 16);
271+
}
272+
}

poppy/src/bitset/vec.rs

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ impl VecBitSet {
5555
// equivalent to index % 8
5656
let mask = (value as u8) << (index & 7);
5757
let old = self.0[iblock] & mask == mask;
58-
self.0[iblock] |= mask;
58+
if value {
59+
self.0[iblock] |= mask;
60+
} else {
61+
self.0[iblock] &= mask;
62+
}
5963
old
6064
}
6165

@@ -149,3 +153,108 @@ impl VecBitSet {
149153
self.0.iter().map(|b| b.count_zeros() as usize).sum()
150154
}
151155
}
156+
157+
#[cfg(test)]
158+
mod tests {
159+
use super::*;
160+
161+
#[test]
162+
fn test_with_bit_capacity() {
163+
let capacity = 10;
164+
let bitset = VecBitSet::with_bit_capacity(capacity);
165+
assert_eq!(bitset.bit_len(), 16); // because of byte alignment, with capacity 10 it's 16 bits (2 bytes)
166+
assert_eq!(bitset.byte_len(), 2);
167+
}
168+
169+
#[test]
170+
fn test_is_empty() {
171+
let bitset = VecBitSet::with_bit_capacity(0);
172+
assert!(bitset.is_empty());
173+
}
174+
175+
#[test]
176+
fn test_set_nth_bit() {
177+
let mut bitset = VecBitSet::with_bit_capacity(8);
178+
assert!(!bitset.get_nth_bit(0));
179+
bitset.set_nth_bit(0);
180+
assert!(bitset.get_nth_bit(0));
181+
}
182+
183+
#[test]
184+
fn test_unset_nth_bit() {
185+
let mut bitset = VecBitSet::with_bit_capacity(8);
186+
bitset.set_nth_bit(0);
187+
assert!(bitset.get_nth_bit(0));
188+
bitset.unset_nth_bit(0);
189+
assert!(!bitset.get_nth_bit(0));
190+
}
191+
192+
#[test]
193+
fn test_clear() {
194+
let mut bitset = VecBitSet::with_bit_capacity(8);
195+
bitset.set_nth_bit(0);
196+
bitset.set_nth_bit(1);
197+
bitset.clear();
198+
assert_eq!(bitset.count_ones(), 0);
199+
}
200+
201+
#[test]
202+
fn test_union() {
203+
let mut bitset1 = VecBitSet::with_bit_capacity(8);
204+
let mut bitset2 = VecBitSet::with_bit_capacity(8);
205+
bitset1.set_nth_bit(0);
206+
bitset2.set_nth_bit(1);
207+
bitset1.union(&bitset2);
208+
assert!(bitset1.get_nth_bit(0));
209+
assert!(bitset1.get_nth_bit(1));
210+
}
211+
212+
#[test]
213+
fn test_intersection() {
214+
let mut bitset1 = VecBitSet::with_bit_capacity(8);
215+
let mut bitset2 = VecBitSet::with_bit_capacity(8);
216+
bitset1.set_nth_bit(0);
217+
bitset1.set_nth_bit(1);
218+
bitset2.set_nth_bit(1);
219+
bitset2.set_nth_bit(2);
220+
bitset1.intersection(&bitset2);
221+
assert!(!bitset1.get_nth_bit(0));
222+
assert!(bitset1.get_nth_bit(1));
223+
assert!(!bitset1.get_nth_bit(2));
224+
}
225+
226+
#[test]
227+
fn test_count_ones_in_common() {
228+
let mut bitset1 = VecBitSet::with_bit_capacity(8);
229+
let mut bitset2 = VecBitSet::with_bit_capacity(8);
230+
bitset1.set_nth_bit(0);
231+
bitset1.set_nth_bit(1);
232+
bitset2.set_nth_bit(1);
233+
bitset2.set_nth_bit(2);
234+
assert_eq!(bitset1.count_ones_in_common(&bitset2), 1);
235+
}
236+
237+
#[test]
238+
fn test_count_ones() {
239+
let mut bitset = VecBitSet::with_bit_capacity(8);
240+
bitset.set_nth_bit(0);
241+
bitset.set_nth_bit(1);
242+
assert_eq!(bitset.count_ones(), 2);
243+
}
244+
245+
#[test]
246+
fn test_count_zeros() {
247+
let mut bitset = VecBitSet::with_bit_capacity(8);
248+
bitset.set_nth_bit(0);
249+
bitset.set_nth_bit(1);
250+
assert_eq!(bitset.count_zeros(), 6);
251+
}
252+
253+
#[test]
254+
#[should_panic]
255+
fn test_out_of_bounds_access() {
256+
let bitset = VecBitSet::with_bit_capacity(8);
257+
// should panic but handled in the test if it does.
258+
bitset.get_nth_bit(8);
259+
}
260+
}

0 commit comments

Comments
 (0)