rose_bitsets/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
3use rose_bitset_derive::BitSet;
4
5/// A set of 8 bits.
6#[cfg(feature = "b8")]
7#[cfg_attr(docsrs, doc(cfg(feature = "b8")))]
8#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
9#[bitset(debug, indices, iter, tests)]
10pub struct BitSet8(u8);
11
12/// A set of 16 bits.
13#[cfg(feature = "b16")]
14#[cfg_attr(docsrs, doc(cfg(feature = "b16")))]
15#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
16#[bitset(debug, indices, iter, tests)]
17pub struct BitSet16(u16);
18
19/// A set of 32 bits.
20#[cfg(feature = "b32")]
21#[cfg_attr(docsrs, doc(cfg(feature = "b32")))]
22#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
23#[bitset(debug, indices, iter, tests)]
24pub struct BitSet32(u32);
25
26/// A set of 64 bits.
27#[cfg(feature = "b64")]
28#[cfg_attr(docsrs, doc(cfg(feature = "b64")))]
29#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
30#[bitset(debug, indices, iter, tests)]
31pub struct BitSet64(u64);
32
33/// A set of 128 bits.
34#[cfg(feature = "b128")]
35#[cfg_attr(docsrs, doc(cfg(feature = "b128")))]
36#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
37#[bitset(debug, indices, iter, tests)]
38pub struct BitSet128(u128);
39
40/// A bitset the length of a pointer.
41///
42/// I doubt there's a good use for a type like this, but it's here for the sake of completeness
43/// (though it is locked behind a feature flag that's disabled by default).
44#[cfg(feature = "bsize")]
45#[cfg_attr(docsrs, doc(cfg(feature = "bsize")))]
46#[derive(BitSet, Clone, Copy, Default, Eq, Hash, PartialEq)]
47#[bitset(debug, indices, iter, tests)]
48pub struct BitSetSize(usize);
49
50/// An iteration order that starts with the smallest end/items and ends with the largest.
51pub struct Ascending;
52
53/// An iteration order that starts with the largest end/items and ends with the smallest.
54pub struct Descending;
55
56#[cfg(test)]
57mod iter_tests {
58    #[cfg(feature = "rose-bitset-derive")]
59    use crate::{Ascending, Descending};
60    #[cfg(feature = "rose-bitset-derive")]
61    use rstest::rstest;
62    #[cfg(feature = "rose-bitset-derive")]
63    use std::iter::zip;
64
65    #[cfg(feature = "b8")]
66    mod b8 {
67        use super::*;
68        use crate::BitSet8;
69
70        const SET_1: BitSet8 = BitSet8::from_bits(0b00101110);
71        const INDICES_1: &[usize] = &[1, 2, 3, 5];
72        const BITS_1: &[bool; 8] = &[false, true, true, true, false, true, false, false];
73
74        const SET_2: BitSet8 = BitSet8::from_bits(0b10000101);
75        const INDICES_2: &[usize] = &[0, 2, 7];
76        const BITS_2: &[bool; 8] = &[true, false, true, false, false, false, false, true];
77
78        const SET_3: BitSet8 = BitSet8::from_bits(0b01100101);
79        const INDICES_3: &[usize] = &[0, 2, 5, 6];
80        const BITS_3: &[bool; 8] = &[true, false, true, false, false, true, true, false];
81
82        const SET_4: BitSet8 = BitSet8::from_bits(0b01101011);
83        const INDICES_4: &[usize] = &[0, 1, 3, 5, 6];
84        const BITS_4: &[bool; 8] = &[true, true, false, true, false, true, true, false];
85
86        const SET_5: BitSet8 = BitSet8::new();
87        const INDICES_5: &[usize] = &[];
88        const BITS_5: &[bool; 8] = &[false; 8];
89
90        const SET_6: BitSet8 = BitSet8::all();
91        const INDICES_6: &[usize] = &[0, 1, 2, 3, 4, 5, 6, 7];
92        const BITS_6: &[bool; 8] = &[true; 8];
93
94        #[rstest]
95        #[case(SET_1, INDICES_1)]
96        #[case(SET_2, INDICES_2)]
97        #[case(SET_3, INDICES_3)]
98        #[case(SET_4, INDICES_4)]
99        #[case(SET_5, INDICES_5)]
100        #[case(SET_6, INDICES_6)]
101        fn ascending_indices(#[case] set: BitSet8, #[case] indices: &[usize]) {
102            for (&lhs, rhs) in zip(indices, set.iter_indices::<Ascending>()) {
103                assert_eq!(lhs, rhs);
104            }
105        }
106
107        #[rstest]
108        #[case(SET_1, INDICES_1)]
109        #[case(SET_2, INDICES_2)]
110        #[case(SET_3, INDICES_3)]
111        #[case(SET_4, INDICES_4)]
112        #[case(SET_5, INDICES_5)]
113        #[case(SET_6, INDICES_6)]
114        fn descending_indices(#[case] set: BitSet8, #[case] indices: &[usize]) {
115            for (&lhs, rhs) in zip(indices.iter().rev(), set.iter_indices::<Descending>()) {
116                assert_eq!(lhs, rhs);
117            }
118        }
119
120        #[rstest]
121        #[case(SET_1, BITS_1)]
122        #[case(SET_2, BITS_2)]
123        #[case(SET_3, BITS_3)]
124        #[case(SET_4, BITS_4)]
125        #[case(SET_5, BITS_5)]
126        #[case(SET_6, BITS_6)]
127        fn ascending_bits(#[case] set: BitSet8, #[case] bits: &[bool]) {
128            for (&lhs, rhs) in zip(bits, set.iter_bits::<Ascending>()) {
129                assert_eq!(lhs, rhs);
130            }
131        }
132
133        #[rstest]
134        #[case(SET_1, BITS_1)]
135        #[case(SET_2, BITS_2)]
136        #[case(SET_3, BITS_3)]
137        #[case(SET_4, BITS_4)]
138        #[case(SET_5, BITS_5)]
139        #[case(SET_6, BITS_6)]
140        fn descending_bits(#[case] set: BitSet8, #[case] bits: &[bool]) {
141            for (&lhs, rhs) in zip(bits.iter().rev(), set.iter_bits::<Descending>()) {
142                assert_eq!(lhs, rhs);
143            }
144        }
145    }
146
147    #[cfg(feature = "b16")]
148    mod b16 {
149        use super::*;
150        use crate::BitSet16;
151
152        const SET_1: BitSet16 = BitSet16::from_bits(0b1010011001000000);
153        const INDICES_1: &[usize] = &[6, 9, 10, 13, 15];
154        const BITS_1: &[bool; 16] = &[
155            false, false, false, false, false, false, true, false, false, true, true, false, false,
156            true, false, true,
157        ];
158
159        const SET_2: BitSet16 = BitSet16::from_bits(0b1100000011000010);
160        const INDICES_2: &[usize] = &[1, 6, 7, 14, 15];
161        const BITS_2: &[bool; 16] = &[
162            false, true, false, false, false, false, true, true, false, false, false, false, false,
163            false, true, true,
164        ];
165
166        const SET_3: BitSet16 = BitSet16::from_bits(0b1111111001000011);
167        const INDICES_3: &[usize] = &[0, 1, 6, 9, 10, 11, 12, 13, 14, 15];
168        const BITS_3: &[bool; 16] = &[
169            true, true, false, false, false, false, true, false, false, true, true, true, true,
170            true, true, true,
171        ];
172
173        const SET_4: BitSet16 = BitSet16::from_bits(0b1101100010101011);
174        const INDICES_4: &[usize] = &[0, 1, 3, 5, 7, 11, 12, 14, 15];
175        const BITS_4: &[bool; 16] = &[
176            true, true, false, true, false, true, false, true, false, false, false, true, true,
177            false, true, true,
178        ];
179
180        const SET_5: BitSet16 = BitSet16::new();
181        const INDICES_5: &[usize] = &[];
182        const BITS_5: &[bool; 16] = &[false; 16];
183
184        const SET_6: BitSet16 = BitSet16::all();
185        const INDICES_6: &[usize] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
186        const BITS_6: &[bool; 16] = &[true; 16];
187
188        #[rstest]
189        #[case(SET_1, INDICES_1)]
190        #[case(SET_2, INDICES_2)]
191        #[case(SET_3, INDICES_3)]
192        #[case(SET_4, INDICES_4)]
193        #[case(SET_5, INDICES_5)]
194        #[case(SET_6, INDICES_6)]
195        fn ascending_indices(#[case] set: BitSet16, #[case] indices: &[usize]) {
196            for (&lhs, rhs) in zip(indices, set.iter_indices::<Ascending>()) {
197                assert_eq!(lhs, rhs);
198            }
199        }
200
201        #[rstest]
202        #[case(SET_1, INDICES_1)]
203        #[case(SET_2, INDICES_2)]
204        #[case(SET_3, INDICES_3)]
205        #[case(SET_4, INDICES_4)]
206        #[case(SET_5, INDICES_5)]
207        #[case(SET_6, INDICES_6)]
208        fn descending_indices(#[case] set: BitSet16, #[case] indices: &[usize]) {
209            for (&lhs, rhs) in zip(indices.iter().rev(), set.iter_indices::<Descending>()) {
210                assert_eq!(lhs, rhs);
211            }
212        }
213
214        #[rstest]
215        #[case(SET_1, BITS_1)]
216        #[case(SET_2, BITS_2)]
217        #[case(SET_3, BITS_3)]
218        #[case(SET_4, BITS_4)]
219        #[case(SET_5, BITS_5)]
220        #[case(SET_6, BITS_6)]
221        fn ascending_bits(#[case] set: BitSet16, #[case] bits: &[bool]) {
222            for (&lhs, rhs) in zip(bits, set.iter_bits::<Ascending>()) {
223                assert_eq!(lhs, rhs);
224            }
225        }
226
227        #[rstest]
228        #[case(SET_1, BITS_1)]
229        #[case(SET_2, BITS_2)]
230        #[case(SET_3, BITS_3)]
231        #[case(SET_4, BITS_4)]
232        #[case(SET_5, BITS_5)]
233        #[case(SET_6, BITS_6)]
234        fn descending_bits(#[case] set: BitSet16, #[case] bits: &[bool]) {
235            for (&lhs, rhs) in zip(bits.iter().rev(), set.iter_bits::<Descending>()) {
236                assert_eq!(lhs, rhs);
237            }
238        }
239    }
240
241    #[cfg(feature = "b32")]
242    mod b32 {
243        use super::*;
244        use crate::BitSet32;
245
246        const SET_1: BitSet32 = BitSet32::from_bits(0x9fcfc89d);
247        const INDICES_1: &[usize] = &[
248            0, 2, 3, 4, 7, 11, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 31,
249        ];
250        const BITS_1: &[bool; 32] = &[
251            true, false, true, true, true, false, false, true, false, false, false, true, false,
252            false, true, true, true, true, true, true, false, false, true, true, true, true, true,
253            true, true, false, false, true,
254        ];
255
256        const SET_2: BitSet32 = BitSet32::from_bits(0xa8e4862e);
257        const INDICES_2: &[usize] = &[1, 2, 3, 5, 9, 10, 15, 18, 21, 22, 23, 27, 29, 31];
258        const BITS_2: &[bool; 32] = &[
259            false, true, true, true, false, true, false, false, false, true, true, false, false,
260            false, false, true, false, false, true, false, false, true, true, true, false, false,
261            false, true, false, true, false, true,
262        ];
263
264        const SET_3: BitSet32 = BitSet32::from_bits(0x0876a181);
265        const INDICES_3: &[usize] = &[0, 7, 8, 13, 15, 17, 18, 20, 21, 22, 27];
266        const BITS_3: &[bool; 32] = &[
267            true, false, false, false, false, false, false, true, true, false, false, false, false,
268            true, false, true, false, true, true, false, true, true, true, false, false, false,
269            false, true, false, false, false, false,
270        ];
271
272        const SET_4: BitSet32 = BitSet32::from_bits(0x667e1426);
273        const INDICES_4: &[usize] = &[1, 2, 5, 10, 12, 17, 18, 19, 20, 21, 22, 25, 26, 29, 30];
274        const BITS_4: &[bool; 32] = &[
275            false, true, true, false, false, true, false, false, false, false, true, false, true,
276            false, false, false, false, true, true, true, true, true, true, false, false, true,
277            true, false, false, true, true, false,
278        ];
279
280        const SET_5: BitSet32 = BitSet32::new();
281        const INDICES_5: &[usize] = &[];
282        const BITS_5: &[bool; 32] = &[false; 32];
283
284        const SET_6: BitSet32 = BitSet32::all();
285        const INDICES_6: &[usize] = &[
286            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
287            24, 25, 26, 27, 28, 29, 30, 31,
288        ];
289        const BITS_6: &[bool; 32] = &[true; 32];
290
291        #[rstest]
292        #[case(SET_1, INDICES_1)]
293        #[case(SET_2, INDICES_2)]
294        #[case(SET_3, INDICES_3)]
295        #[case(SET_4, INDICES_4)]
296        #[case(SET_5, INDICES_5)]
297        #[case(SET_6, INDICES_6)]
298        fn ascending_indices(#[case] set: BitSet32, #[case] indices: &[usize]) {
299            for (&lhs, rhs) in zip(indices, set.iter_indices::<Ascending>()) {
300                assert_eq!(lhs, rhs);
301            }
302        }
303
304        #[rstest]
305        #[case(SET_1, INDICES_1)]
306        #[case(SET_2, INDICES_2)]
307        #[case(SET_3, INDICES_3)]
308        #[case(SET_4, INDICES_4)]
309        #[case(SET_5, INDICES_5)]
310        #[case(SET_6, INDICES_6)]
311        fn descending_indices(#[case] set: BitSet32, #[case] indices: &[usize]) {
312            for (&lhs, rhs) in zip(indices.iter().rev(), set.iter_indices::<Descending>()) {
313                assert_eq!(lhs, rhs);
314            }
315        }
316
317        #[rstest]
318        #[case(SET_1, BITS_1)]
319        #[case(SET_2, BITS_2)]
320        #[case(SET_3, BITS_3)]
321        #[case(SET_4, BITS_4)]
322        #[case(SET_5, BITS_5)]
323        #[case(SET_6, BITS_6)]
324        fn ascending_bits(#[case] set: BitSet32, #[case] bits: &[bool]) {
325            for (&lhs, rhs) in zip(bits, set.iter_bits::<Ascending>()) {
326                assert_eq!(lhs, rhs);
327            }
328        }
329
330        #[rstest]
331        #[case(SET_1, BITS_1)]
332        #[case(SET_2, BITS_2)]
333        #[case(SET_3, BITS_3)]
334        #[case(SET_4, BITS_4)]
335        #[case(SET_5, BITS_5)]
336        #[case(SET_6, BITS_6)]
337        fn descending_bits(#[case] set: BitSet32, #[case] bits: &[bool]) {
338            for (&lhs, rhs) in zip(bits.iter().rev(), set.iter_bits::<Descending>()) {
339                assert_eq!(lhs, rhs);
340            }
341        }
342    }
343
344    #[cfg(feature = "b64")]
345    mod b64 {
346        use super::*;
347        use crate::BitSet64;
348
349        const SET_1: BitSet64 = BitSet64::from_bits(0x64dc46ef58cbc169);
350        const INDICES_1: &[usize] = &[
351            0, 3, 5, 6, 8, 14, 15, 16, 17, 19, 22, 23, 27, 28, 30, 32, 33, 34, 35, 37, 38, 39, 41,
352            42, 46, 50, 51, 52, 54, 55, 58, 61, 62,
353        ];
354        const BITS_1: &[bool; 64] = &[
355            true, false, false, true, false, true, true, false, true, false, false, false, false,
356            false, true, true, true, true, false, true, false, false, true, true, false, false,
357            false, true, true, false, true, false, true, true, true, true, false, true, true, true,
358            false, true, true, false, false, false, true, false, false, false, true, true, true,
359            false, true, true, false, false, true, false, false, true, true, false,
360        ];
361
362        const SET_2: BitSet64 = BitSet64::from_bits(0x5df951b7aaac5647);
363        const INDICES_2: &[usize] = &[
364            0, 1, 2, 6, 9, 10, 12, 14, 18, 19, 21, 23, 25, 27, 29, 31, 32, 33, 34, 36, 37, 39, 40,
365            44, 46, 48, 51, 52, 53, 54, 55, 56, 58, 59, 60, 62,
366        ];
367        const BITS_2: &[bool; 64] = &[
368            true, true, true, false, false, false, true, false, false, true, true, false, true,
369            false, true, false, false, false, true, true, false, true, false, true, false, true,
370            false, true, false, true, false, true, true, true, true, false, true, true, false,
371            true, true, false, false, false, true, false, true, false, true, false, false, true,
372            true, true, true, true, true, false, true, true, true, false, true, false,
373        ];
374
375        const SET_3: BitSet64 = BitSet64::from_bits(0x0863f744162ebcfd);
376        const INDICES_3: &[usize] = &[
377            0, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 15, 17, 18, 19, 21, 25, 26, 28, 34, 38, 40, 41,
378            42, 44, 45, 46, 47, 48, 49, 53, 54, 59,
379        ];
380        const BITS_3: &[bool; 64] = &[
381            true, false, true, true, true, true, true, true, false, false, true, true, true, true,
382            false, true, false, true, true, true, false, true, false, false, false, true, true,
383            false, true, false, false, false, false, false, true, false, false, false, true, false,
384            true, true, true, false, true, true, true, true, true, true, false, false, false, true,
385            true, false, false, false, false, true, false, false, false, false,
386        ];
387
388        const SET_4: BitSet64 = BitSet64::from_bits(0x21ce32fc5754e1db);
389        const INDICES_4: &[usize] = &[
390            0, 1, 3, 4, 6, 7, 8, 13, 14, 15, 18, 20, 22, 24, 25, 26, 28, 30, 34, 35, 36, 37, 38,
391            39, 41, 44, 45, 49, 50, 51, 54, 55, 56, 61,
392        ];
393        const BITS_4: &[bool; 64] = &[
394            true, true, false, true, true, false, true, true, true, false, false, false, false,
395            true, true, true, false, false, true, false, true, false, true, false, true, true,
396            true, false, true, false, true, false, false, false, true, true, true, true, true,
397            true, false, true, false, false, true, true, false, false, false, true, true, true,
398            false, false, true, true, true, false, false, false, false, true, false, false,
399        ];
400
401        const SET_5: BitSet64 = BitSet64::new();
402        const INDICES_5: &[usize] = &[];
403        const BITS_5: &[bool; 64] = &[false; 64];
404
405        const SET_6: BitSet64 = BitSet64::all();
406        const INDICES_6: &[usize] = &[
407            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
408            24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
409            46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
410        ];
411        const BITS_6: &[bool; 64] = &[true; 64];
412
413        #[rstest]
414        #[case(SET_1, INDICES_1)]
415        #[case(SET_2, INDICES_2)]
416        #[case(SET_3, INDICES_3)]
417        #[case(SET_4, INDICES_4)]
418        #[case(SET_5, INDICES_5)]
419        #[case(SET_6, INDICES_6)]
420        fn ascending_indices(#[case] set: BitSet64, #[case] indices: &[usize]) {
421            for (&lhs, rhs) in zip(indices, set.iter_indices::<Ascending>()) {
422                assert_eq!(lhs, rhs);
423            }
424        }
425
426        #[rstest]
427        #[case(SET_1, INDICES_1)]
428        #[case(SET_2, INDICES_2)]
429        #[case(SET_3, INDICES_3)]
430        #[case(SET_4, INDICES_4)]
431        #[case(SET_5, INDICES_5)]
432        #[case(SET_6, INDICES_6)]
433        fn descending_indices(#[case] set: BitSet64, #[case] indices: &[usize]) {
434            for (&lhs, rhs) in zip(indices.iter().rev(), set.iter_indices::<Descending>()) {
435                assert_eq!(lhs, rhs);
436            }
437        }
438
439        #[rstest]
440        #[case(SET_1, BITS_1)]
441        #[case(SET_2, BITS_2)]
442        #[case(SET_3, BITS_3)]
443        #[case(SET_4, BITS_4)]
444        #[case(SET_5, BITS_5)]
445        #[case(SET_6, BITS_6)]
446        fn ascending_bits(#[case] set: BitSet64, #[case] bits: &[bool]) {
447            for (&lhs, rhs) in zip(bits, set.iter_bits::<Ascending>()) {
448                assert_eq!(lhs, rhs);
449            }
450        }
451
452        #[rstest]
453        #[case(SET_1, BITS_1)]
454        #[case(SET_2, BITS_2)]
455        #[case(SET_3, BITS_3)]
456        #[case(SET_4, BITS_4)]
457        #[case(SET_5, BITS_5)]
458        #[case(SET_6, BITS_6)]
459        fn descending_bits(#[case] set: BitSet64, #[case] bits: &[bool]) {
460            for (&lhs, rhs) in zip(bits.iter().rev(), set.iter_bits::<Descending>()) {
461                assert_eq!(lhs, rhs);
462            }
463        }
464    }
465}