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