cranelift_bitset/
scalar.rs

1//! Scalar bitsets.
2
3use core::mem::size_of;
4use core::ops::{Add, BitAnd, BitOr, Not, Shl, Shr, Sub};
5
6/// A small bitset built on top of a single primitive integer type.
7///
8/// # Example
9///
10/// ```
11/// use cranelift_bitset::ScalarBitSet;
12///
13/// // Create a new bitset backed with a `u32`.
14/// let mut bitset = ScalarBitSet::<u32>::new();
15///
16/// // Bitsets are initially empty.
17/// assert!(bitset.is_empty());
18/// assert_eq!(bitset.len(), 0);
19///
20/// // Insert into the bitset.
21/// bitset.insert(4);
22/// bitset.insert(5);
23/// bitset.insert(6);
24///
25/// // Now the bitset is not empty.
26/// assert_eq!(bitset.len(), 3);
27/// assert!(!bitset.is_empty());
28/// assert!(bitset.contains(4));
29/// assert!(bitset.contains(5));
30/// assert!(bitset.contains(6));
31///
32/// // Remove an element from the bitset.
33/// let was_present = bitset.remove(6);
34/// assert!(was_present);
35/// assert!(!bitset.contains(6));
36/// assert_eq!(bitset.len(), 2);
37///
38/// // Can iterate over the elements in the set.
39/// let elems: Vec<_> = bitset.iter().collect();
40/// assert_eq!(elems, [4, 5]);
41/// ```
42#[derive(Clone, Copy, PartialEq, Eq)]
43#[cfg_attr(
44    feature = "enable-serde",
45    derive(serde_derive::Serialize, serde_derive::Deserialize)
46)]
47pub struct ScalarBitSet<T>(pub T);
48
49impl<T> core::fmt::Debug for ScalarBitSet<T>
50where
51    T: ScalarBitSetStorage,
52{
53    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54        let mut s = f.debug_struct(core::any::type_name::<Self>());
55        for i in 0..Self::capacity() {
56            use alloc::string::ToString;
57            let i = u8::try_from(i).unwrap();
58            s.field(&i.to_string(), &self.contains(i));
59        }
60        s.finish()
61    }
62}
63
64impl<T> Default for ScalarBitSet<T>
65where
66    T: ScalarBitSetStorage,
67{
68    #[inline]
69    fn default() -> Self {
70        Self::new()
71    }
72}
73
74impl<T> ScalarBitSet<T>
75where
76    T: ScalarBitSetStorage,
77{
78    /// Create a new, empty bitset.
79    ///
80    /// # Example
81    ///
82    /// ```
83    /// use cranelift_bitset::ScalarBitSet;
84    ///
85    /// let bitset = ScalarBitSet::<u64>::new();
86    ///
87    /// assert!(bitset.is_empty());
88    /// ```
89    #[inline]
90    pub fn new() -> Self {
91        Self(T::from(0))
92    }
93
94    /// Construct a bitset with the half-open range `[lo, hi)` inserted.
95    ///
96    /// # Example
97    ///
98    /// ```
99    /// use cranelift_bitset::ScalarBitSet;
100    ///
101    /// let bitset = ScalarBitSet::<u64>::from_range(3, 6);
102    ///
103    /// assert_eq!(bitset.len(), 3);
104    ///
105    /// assert!(bitset.contains(3));
106    /// assert!(bitset.contains(4));
107    /// assert!(bitset.contains(5));
108    /// ```
109    ///
110    /// # Panics
111    ///
112    /// Panics if `lo > hi` or if `hi > Self::capacity()`.
113    ///
114    /// ```should_panic
115    /// use cranelift_bitset::ScalarBitSet;
116    ///
117    /// // The lower bound may not be larger than the upper bound.
118    /// let bitset = ScalarBitSet::<u64>::from_range(6, 3);
119    /// ```
120    ///
121    /// ```should_panic
122    /// use cranelift_bitset::ScalarBitSet;
123    ///
124    /// // The bounds must fit within the backing scalar type.
125    /// let bitset = ScalarBitSet::<u64>::from_range(3, 69);
126    /// ```
127    #[inline]
128    pub fn from_range(lo: u8, hi: u8) -> Self {
129        assert!(lo <= hi);
130        assert!(hi <= Self::capacity());
131
132        let one = T::from(1);
133
134        // We can't just do (one << hi) - one here as the shift may overflow
135        let hi_rng = if hi >= 1 {
136            (one << (hi - 1)) + ((one << (hi - 1)) - one)
137        } else {
138            T::from(0)
139        };
140
141        let lo_rng = (one << lo) - one;
142
143        Self(hi_rng - lo_rng)
144    }
145
146    /// The maximum number of bits that can be stored in this bitset.
147    ///
148    /// If you need more bits than this, use a
149    /// [`CompoundBitSet`][crate::CompoundBitSet] instead of a `ScalarBitSet`.
150    ///
151    /// # Example
152    ///
153    /// ```
154    /// use cranelift_bitset::ScalarBitSet;
155    ///
156    /// assert_eq!(ScalarBitSet::<u8>::capacity(), 8);
157    /// assert_eq!(ScalarBitSet::<u64>::capacity(), 64);
158    /// ```
159    #[inline]
160    pub fn capacity() -> u8 {
161        u8::try_from(size_of::<T>()).unwrap() * 8
162    }
163
164    /// Get the number of elements in this set.
165    ///
166    /// # Example
167    ///
168    /// ```
169    /// use cranelift_bitset::ScalarBitSet;
170    ///
171    /// let mut bitset = ScalarBitSet::<u64>::new();
172    ///
173    /// assert_eq!(bitset.len(), 0);
174    ///
175    /// bitset.insert(24);
176    /// bitset.insert(13);
177    /// bitset.insert(36);
178    ///
179    /// assert_eq!(bitset.len(), 3);
180    /// ```
181    #[inline]
182    pub fn len(&self) -> u8 {
183        self.0.count_ones()
184    }
185
186    /// Is this bitset empty?
187    ///
188    /// # Example
189    ///
190    /// ```
191    /// use cranelift_bitset::ScalarBitSet;
192    ///
193    /// let mut bitset = ScalarBitSet::<u16>::new();
194    ///
195    /// assert!(bitset.is_empty());
196    ///
197    /// bitset.insert(10);
198    ///
199    /// assert!(!bitset.is_empty());
200    /// ```
201    #[inline]
202    pub fn is_empty(&self) -> bool {
203        self.0 == T::from(0)
204    }
205
206    /// Check whether this bitset contains `i`.
207    ///
208    /// # Example
209    ///
210    /// ```
211    /// use cranelift_bitset::ScalarBitSet;
212    ///
213    /// let mut bitset = ScalarBitSet::<u8>::new();
214    ///
215    /// assert!(!bitset.contains(7));
216    ///
217    /// bitset.insert(7);
218    ///
219    /// assert!(bitset.contains(7));
220    /// ```
221    ///
222    /// # Panics
223    ///
224    /// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
225    ///
226    /// ```should_panic
227    /// use cranelift_bitset::ScalarBitSet;
228    ///
229    /// let mut bitset = ScalarBitSet::<u8>::new();
230    ///
231    /// // A `ScalarBitSet<u8>` can only hold the elements `0..=7`, so `8` is
232    /// // out of bounds and will trigger a panic.
233    /// bitset.contains(8);
234    /// ```
235    #[inline]
236    pub fn contains(&self, i: u8) -> bool {
237        assert!(i < Self::capacity());
238        self.0 & (T::from(1) << i) != T::from(0)
239    }
240
241    /// Insert `i` into this bitset.
242    ///
243    /// Returns whether the value was newly inserted. That is:
244    ///
245    /// * If the set did not previously contain `i` then `true` is returned.
246    ///
247    /// * If the set already contained `i` then `false` is returned.
248    ///
249    /// # Example
250    ///
251    /// ```
252    /// use cranelift_bitset::ScalarBitSet;
253    ///
254    /// let mut bitset = ScalarBitSet::<u8>::new();
255    ///
256    /// // When an element is inserted that was not already present in the set,
257    /// // then `true` is returned.
258    /// let is_new = bitset.insert(7);
259    /// assert!(is_new);
260    ///
261    /// // The element is now present in the set.
262    /// assert!(bitset.contains(7));
263    ///
264    /// // And when the element is already in the set, `false` is returned from
265    /// // `insert`.
266    /// let is_new = bitset.insert(7);
267    /// assert!(!is_new);
268    /// ```
269    ///
270    /// # Panics
271    ///
272    /// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
273    ///
274    /// ```should_panic
275    /// use cranelift_bitset::ScalarBitSet;
276    ///
277    /// let mut bitset = ScalarBitSet::<u32>::new();
278    ///
279    /// // A `ScalarBitSet<u32>` can only hold the elements `0..=31`, so `42` is
280    /// // out of bounds and will trigger a panic.
281    /// bitset.insert(42);
282    /// ```
283    #[inline]
284    pub fn insert(&mut self, i: u8) -> bool {
285        let is_new = !self.contains(i);
286        self.0 = self.0 | (T::from(1) << i);
287        is_new
288    }
289
290    /// Remove `i` from this bitset.
291    ///
292    /// Returns whether `i` was previously in this set or not.
293    ///
294    /// # Example
295    ///
296    /// ```
297    /// use cranelift_bitset::ScalarBitSet;
298    ///
299    /// let mut bitset = ScalarBitSet::<u128>::new();
300    ///
301    /// // Removing an element that was not present in the set returns `false`.
302    /// let was_present = bitset.remove(100);
303    /// assert!(!was_present);
304    ///
305    /// // And when the element was in the set, `true` is returned.
306    /// bitset.insert(100);
307    /// let was_present = bitset.remove(100);
308    /// assert!(was_present);
309    /// ```
310    ///
311    /// # Panics
312    ///
313    /// Panics if `i` is greater than or equal to [`Self::capacity()`][Self::capacity].
314    ///
315    /// ```should_panic
316    /// use cranelift_bitset::ScalarBitSet;
317    ///
318    /// let mut bitset = ScalarBitSet::<u16>::new();
319    ///
320    /// // A `ScalarBitSet<u16>` can only hold the elements `0..=15`, so `20` is
321    /// // out of bounds and will trigger a panic.
322    /// bitset.remove(20);
323    /// ```
324    #[inline]
325    pub fn remove(&mut self, i: u8) -> bool {
326        let was_present = self.contains(i);
327        self.0 = self.0 & !(T::from(1) << i);
328        was_present
329    }
330
331    /// Remove all entries from this bitset.
332    ///
333    /// # Example
334    ///
335    /// ```
336    /// use cranelift_bitset::ScalarBitSet;
337    ///
338    /// let mut bitset = ScalarBitSet::<u32>::new();
339    ///
340    /// bitset.insert(10);
341    /// bitset.insert(20);
342    /// bitset.insert(30);
343    ///
344    /// bitset.clear();
345    ///
346    /// assert!(bitset.is_empty());
347    /// ```
348    #[inline]
349    pub fn clear(&mut self) {
350        self.0 = T::from(0);
351    }
352
353    /// Remove and return the smallest value in the bitset.
354    ///
355    /// # Example
356    ///
357    /// ```
358    /// use cranelift_bitset::ScalarBitSet;
359    ///
360    /// let mut bitset = ScalarBitSet::<u64>::new();
361    ///
362    /// bitset.insert(0);
363    /// bitset.insert(24);
364    /// bitset.insert(13);
365    /// bitset.insert(36);
366    ///
367    /// assert_eq!(bitset.pop_min(), Some(0));
368    /// assert_eq!(bitset.pop_min(), Some(13));
369    /// assert_eq!(bitset.pop_min(), Some(24));
370    /// assert_eq!(bitset.pop_min(), Some(36));
371    /// assert_eq!(bitset.pop_min(), None);
372    /// ```
373    #[inline]
374    pub fn pop_min(&mut self) -> Option<u8> {
375        let min = self.min()?;
376        self.remove(min);
377        Some(min)
378    }
379
380    /// Remove and return the largest value in the bitset.
381    ///
382    /// # Example
383    ///
384    /// ```
385    /// use cranelift_bitset::ScalarBitSet;
386    ///
387    /// let mut bitset = ScalarBitSet::<u64>::new();
388    ///
389    /// bitset.insert(0);
390    /// bitset.insert(24);
391    /// bitset.insert(13);
392    /// bitset.insert(36);
393    ///
394    /// assert_eq!(bitset.pop_max(), Some(36));
395    /// assert_eq!(bitset.pop_max(), Some(24));
396    /// assert_eq!(bitset.pop_max(), Some(13));
397    /// assert_eq!(bitset.pop_max(), Some(0));
398    /// assert_eq!(bitset.pop_max(), None);
399    /// ```
400    #[inline]
401    pub fn pop_max(&mut self) -> Option<u8> {
402        let max = self.max()?;
403        self.remove(max);
404        Some(max)
405    }
406
407    /// Return the smallest number contained in this bitset or `None` if this
408    /// bitset is empty.
409    ///
410    /// # Example
411    ///
412    /// ```
413    /// use cranelift_bitset::ScalarBitSet;
414    ///
415    /// let mut bitset = ScalarBitSet::<u64>::new();
416    ///
417    /// // When the bitset is empty, `min` returns `None`.
418    /// assert_eq!(bitset.min(), None);
419    ///
420    /// bitset.insert(28);
421    /// bitset.insert(1);
422    /// bitset.insert(63);
423    ///
424    /// // When the bitset is not empty, it returns the smallest element.
425    /// assert_eq!(bitset.min(), Some(1));
426    /// ```
427    #[inline]
428    pub fn min(&self) -> Option<u8> {
429        if self.0 == T::from(0) {
430            None
431        } else {
432            Some(self.0.trailing_zeros())
433        }
434    }
435
436    /// Return the largest number contained in the bitset or None if this bitset
437    /// is empty
438    ///
439    /// # Example
440    ///
441    /// ```
442    /// use cranelift_bitset::ScalarBitSet;
443    ///
444    /// let mut bitset = ScalarBitSet::<u64>::new();
445    ///
446    /// // When the bitset is empty, `max` returns `None`.
447    /// assert_eq!(bitset.max(), None);
448    ///
449    /// bitset.insert(0);
450    /// bitset.insert(36);
451    /// bitset.insert(49);
452    ///
453    /// // When the bitset is not empty, it returns the smallest element.
454    /// assert_eq!(bitset.max(), Some(49));
455    /// ```
456    #[inline]
457    pub fn max(&self) -> Option<u8> {
458        if self.0 == T::from(0) {
459            None
460        } else {
461            let leading_zeroes = self.0.leading_zeros();
462            Some(Self::capacity() - leading_zeroes - 1)
463        }
464    }
465
466    /// Iterate over the items in this set.
467    ///
468    /// Items are always yielded in sorted order.
469    ///
470    /// # Example
471    ///
472    /// ```
473    /// use cranelift_bitset::ScalarBitSet;
474    ///
475    /// let mut bitset = ScalarBitSet::<u64>::new();
476    ///
477    /// bitset.insert(19);
478    /// bitset.insert(3);
479    /// bitset.insert(63);
480    /// bitset.insert(0);
481    ///
482    /// assert_eq!(
483    ///     bitset.iter().collect::<Vec<_>>(),
484    ///     [0, 3, 19, 63],
485    /// );
486    /// ```
487    #[inline]
488    pub fn iter(self) -> Iter<T> {
489        Iter { bitset: self }
490    }
491}
492
493impl<T> IntoIterator for ScalarBitSet<T>
494where
495    T: ScalarBitSetStorage,
496{
497    type Item = u8;
498
499    type IntoIter = Iter<T>;
500
501    #[inline]
502    fn into_iter(self) -> Self::IntoIter {
503        self.iter()
504    }
505}
506
507impl<'a, T> IntoIterator for &'a ScalarBitSet<T>
508where
509    T: ScalarBitSetStorage,
510{
511    type Item = u8;
512
513    type IntoIter = Iter<T>;
514
515    #[inline]
516    fn into_iter(self) -> Self::IntoIter {
517        self.iter()
518    }
519}
520
521impl<T: ScalarBitSetStorage> From<T> for ScalarBitSet<T> {
522    fn from(bits: T) -> Self {
523        Self(bits)
524    }
525}
526
527/// A trait implemented by all integers that can be used as the backing storage
528/// for a [`ScalarBitSet`].
529///
530/// You shouldn't have to implement this yourself, it is already implemented for
531/// `u{8,16,32,64,128}` and if you need more bits than that, then use
532/// [`CompoundBitSet`][crate::CompoundBitSet] instead.
533pub trait ScalarBitSetStorage:
534    Default
535    + From<u8>
536    + Shl<u8, Output = Self>
537    + Shr<u8, Output = Self>
538    + BitAnd<Output = Self>
539    + BitOr<Output = Self>
540    + Not<Output = Self>
541    + Sub<Output = Self>
542    + Add<Output = Self>
543    + PartialEq
544    + Copy
545{
546    /// Count the number of leading zeros.
547    fn leading_zeros(self) -> u8;
548
549    /// Count the number of trailing zeros.
550    fn trailing_zeros(self) -> u8;
551
552    /// Count the number of bits set in this integer.
553    fn count_ones(self) -> u8;
554}
555
556macro_rules! impl_storage {
557    ( $int:ty ) => {
558        impl ScalarBitSetStorage for $int {
559            #[inline]
560            fn leading_zeros(self) -> u8 {
561                u8::try_from(self.leading_zeros()).unwrap()
562            }
563
564            #[inline]
565            fn trailing_zeros(self) -> u8 {
566                u8::try_from(self.trailing_zeros()).unwrap()
567            }
568
569            #[inline]
570            fn count_ones(self) -> u8 {
571                u8::try_from(self.count_ones()).unwrap()
572            }
573        }
574    };
575}
576
577impl_storage!(u8);
578impl_storage!(u16);
579impl_storage!(u32);
580impl_storage!(u64);
581impl_storage!(u128);
582impl_storage!(usize);
583
584/// An iterator over the elements in a [`ScalarBitSet`].
585pub struct Iter<T> {
586    bitset: ScalarBitSet<T>,
587}
588
589impl<T> Iterator for Iter<T>
590where
591    T: ScalarBitSetStorage,
592{
593    type Item = u8;
594
595    #[inline]
596    fn next(&mut self) -> Option<u8> {
597        self.bitset.pop_min()
598    }
599}
600
601impl<T> DoubleEndedIterator for Iter<T>
602where
603    T: ScalarBitSetStorage,
604{
605    #[inline]
606    fn next_back(&mut self) -> Option<Self::Item> {
607        self.bitset.pop_max()
608    }
609}
610
611impl<T> ExactSizeIterator for Iter<T>
612where
613    T: ScalarBitSetStorage,
614{
615    #[inline]
616    fn len(&self) -> usize {
617        usize::from(self.bitset.len())
618    }
619}
620
621#[cfg(feature = "arbitrary")]
622impl<'a, T> arbitrary::Arbitrary<'a> for ScalarBitSet<T>
623where
624    T: ScalarBitSetStorage + arbitrary::Arbitrary<'a>,
625{
626    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
627        T::arbitrary(u).map(Self)
628    }
629}