bit_ops/
bitpos_iter.rs

1//! Module providing iterators to iterate over set bits in unsigned integers.
2//!
3//! See [`BitsIter`] and [`BitmapIter`]. The latter is included into Rust's
4//! [`Iterator`] API via [`BitposIteratorExt`].
5//!
6//! # Performance
7//!
8//! These iterators have been trimmed for performance and were benchmarked. See
9//! the project's README on GitHub for more details.
10
11use core::fmt::Debug;
12use core::ops::{Add, BitAndAssign, Sub};
13
14/// **Internal helper** trait for [`BitsIter`].
15pub trait Uint:
16    Copy + Eq + Add<Output = Self> + Sub<Output = Self> + Sized + BitAndAssign + TryInto<usize>
17{
18    /// Number of bits of that type.
19    const BITS: usize;
20    /// `0` value of the underlying primitive type.
21    const ZERO: Self;
22    /// `1` value of the underlying primitive type.
23    const ONE: Self;
24    /// Number of trailing zeroes.
25    fn trailing_zeros(self) -> Self;
26}
27
28/// Implements the relevant bit operations for the specified primitive type.
29///
30/// Note that the bit positions start at `0`. The highest `bit` position thus
31/// is `BITS - 1`.
32macro_rules! impl_uint_trait {
33    ($primitive_ty:ty) => {
34        impl Uint for $primitive_ty {
35            const BITS: usize = <$primitive_ty>::BITS as usize;
36            const ZERO: Self = 0;
37            const ONE: Self = 1;
38
39            fn trailing_zeros(self) -> Self {
40                <$primitive_ty>::trailing_zeros(self) as Self
41            }
42        }
43    };
44}
45
46impl_uint_trait!(u8);
47impl_uint_trait!(u16);
48impl_uint_trait!(u32);
49impl_uint_trait!(u64);
50impl_uint_trait!(u128);
51impl_uint_trait!(usize);
52
53/// Iterator over set bits of an unsigned integer.
54///
55/// The index / bit position starts at `0`, the last bit position is
56/// `n_bits - 1`.
57///
58/// The iterator can be used with [`u8`], [`u16`], [`u32`], [`u64`], [`u128`],
59/// and [`usize`].
60///
61/// # Example
62/// ```rust
63/// # use bit_ops::BitsIter;
64/// // also works with u16, u32, u64, u128, and usize
65/// let iter = BitsIter::<u8>::new(0);
66/// assert_eq!(&iter.collect::<Vec<_>>(), &[]);
67///
68/// let iter = BitsIter::<u8>::new(1);
69/// assert_eq!(&iter.collect::<Vec<_>>(), &[0]);
70///
71/// let iter = BitsIter::<u8>::new(0b1010_1010);
72/// assert_eq!(&iter.collect::<Vec<_>>(), &[1, 3, 5, 7]);
73/// ```
74#[derive(Debug)]
75pub struct BitsIter<U> {
76    value: U,
77}
78
79impl<U: Uint> BitsIter<U>
80where
81    <U as TryInto<usize>>::Error: Debug,
82{
83    /// Creates a new iterator.
84    pub const fn new(value: U) -> Self {
85        Self { value }
86    }
87}
88
89impl<U: Uint> Iterator for BitsIter<U>
90where
91    <U as TryInto<usize>>::Error: Debug,
92{
93    type Item = U;
94
95    #[inline]
96    fn next(&mut self) -> Option<Self::Item> {
97        if self.value == U::ZERO {
98            return None;
99        }
100        let tz = self.value.trailing_zeros();
101        self.value &= self.value - U::ONE; // clear lowest set bit
102        Some(tz)
103    }
104}
105
106/// Iterator over set bits in (large) bitmaps, i.e., collection of unsigned
107/// integers.
108///
109/// This wraps an iterator emitting corresponding unsigned integers and
110/// uses [`BitsIter`] on each element. While doing so, [`BitmapIter`] keeps
111/// track of consumed elements to properly report the bit position relative to
112/// the very first bit. We basically treat the incoming [`Uint`]s as one
113/// gigantic integer and just spit out which bits are set.
114///
115/// The iterator can be used with [`u8`], [`u16`], [`u32`], [`u64`], [`u128`],
116/// and [`usize`]. The [`BitposIteratorExt`] offers a convenient way to
117/// integrate this iterator in typical iterator chains.
118///
119/// # Example
120///
121/// ## Direct Usage of Iterator
122/// ```rust
123/// use bit_ops::BitmapIter;
124///
125/// // also works with u16, u32, u64, u128, and usize
126/// let iter = BitmapIter::<u8, _>::new([0b1111_0010, 0b1000, 1].into_iter());
127/// assert_eq!(&iter.collect::<Vec<_>>(), &[1, 4, 5, 6, 7, 11, 16]);
128/// ```
129///
130/// ## Use via Iterator Trait Extension
131/// ```rust
132/// use bit_ops::BitposIteratorExt;
133///
134/// // also works with u16, u32, u64, u128, and usize
135/// let bit_pos = [0b1111_0010_u8, 0b1000, 1].into_iter()
136///     .bit_positions()
137///     .collect::<Vec<_>>();
138/// assert_eq!(&bit_pos, &[1, 4, 5, 6, 7, 11, 16]);
139/// ```
140#[derive(Debug)]
141pub struct BitmapIter<U, I> {
142    bitmap_iter: I,
143    consumed_count: usize,
144    current_element_it: BitsIter<U>,
145}
146
147impl<U: Uint, I: Iterator<Item = U>> BitmapIter<U, I>
148where
149    <U as TryInto<usize>>::Error: Debug,
150{
151    /// Creates a new iterator.
152    ///
153    /// This consumes everything that implements [`IntoIterator`] for an
154    /// [`Iterator`] of the corresponding [`Uint`].
155    ///
156    /// # Example
157    /// ```rust
158    /// # use bit_ops::BitmapIter;
159    /// let _ = BitmapIter::<u8, _>::new([0_u8]);
160    /// let _ = BitmapIter::<u16, _>::new([0_u16].iter().copied());
161    /// let _ = BitmapIter::<u16, _>::new((&[0_u16]).iter().copied());
162    /// let _ = BitmapIter::<usize, _>::new((vec![42_usize]));
163    /// ```
164    pub fn new<In: IntoIterator<IntoIter = I>>(bitmap_iter: In) -> Self {
165        let mut bitmap_iter = bitmap_iter.into_iter();
166        let current_element_it = BitsIter::new(bitmap_iter.next().unwrap_or(U::ZERO));
167        Self {
168            bitmap_iter,
169            consumed_count: 0,
170            current_element_it,
171        }
172    }
173}
174
175impl<U: Uint, I: Iterator<Item = U>> Iterator for BitmapIter<U, I>
176where
177    <U as TryInto<usize>>::Error: Debug,
178{
179    type Item = usize;
180
181    #[inline]
182    fn next(&mut self) -> Option<Self::Item> {
183        loop {
184            // We return here, if we currently have an element.
185            if let Some(bit) = self.current_element_it.next() {
186                let bit: usize = bit.try_into().unwrap();
187                return Some(bit + self.consumed_count);
188            }
189
190            // Current byte exhausted: load next one or return `None` / exit.
191            let next_byte = self.bitmap_iter.next()?;
192            self.consumed_count += U::BITS;
193            self.current_element_it = BitsIter::new(next_byte);
194        }
195    }
196}
197
198/// Extension for the Rust standard libraries [`Iterator`] for convenient
199/// integration of [`BitmapIter`].
200pub trait BitposIteratorExt<U: Uint>: Iterator<Item = U> + Sized
201where
202    <U as TryInto<usize>>::Error: Debug,
203{
204    /// Creates an iterator that emits which bits are set.
205    ///
206    /// See [`BitmapIter`] for more details.
207    ///
208    /// # Example
209    /// ```rust
210    /// use bit_ops::BitposIteratorExt;
211    /// let ones = [0b101_u64, 0, 1].into_iter()
212    ///     .bit_positions()
213    ///     .collect::<Vec<_>>();
214    /// assert_eq!(&ones, &[0, 2, 2*64]);
215    /// ```
216    fn bit_positions(self) -> BitmapIter<U, Self> {
217        BitmapIter::new(self)
218    }
219}
220
221// Blanked implementation for all matching iterators.
222impl<U: Uint, I: Iterator<Item = U> + Sized> BitposIteratorExt<U> for I where
223    <U as TryInto<usize>>::Error: Debug
224{
225}
226
227#[cfg(test)]
228mod tests {
229    use super::*;
230    use std::vec::Vec;
231
232    #[test]
233    fn test_bits_iter() {
234        let iter = BitsIter::<u8>::new(0);
235        assert_eq!(&iter.collect::<Vec<_>>(), &[]);
236
237        let iter = BitsIter::<u8>::new(1);
238        assert_eq!(&iter.collect::<Vec<_>>(), &[0]);
239
240        let iter = BitsIter::<u8>::new(0b1010_1010);
241        assert_eq!(&iter.collect::<Vec<_>>(), &[1, 3, 5, 7]);
242
243        let iter = BitsIter::<u8>::new(0b1111_1111);
244        assert_eq!(&iter.collect::<Vec<_>>(), &[0, 1, 2, 3, 4, 5, 6, 7]);
245
246        let iter = BitsIter::<u128>::new(0b1111_1111);
247        assert_eq!(&iter.collect::<Vec<_>>(), &[0, 1, 2, 3, 4, 5, 6, 7]);
248    }
249
250    #[test]
251    fn test_bitmap_iter() {
252        let iter = BitmapIter::<u8, _>::new([0_u8]);
253        assert_eq!(&iter.collect::<Vec<_>>(), &[]);
254
255        let iter = BitmapIter::<u8, _>::new([0b1111_0010, 0b1000, 1]);
256        assert_eq!(&iter.collect::<Vec<_>>(), &[1, 4, 5, 6, 7, 11, 16]);
257
258        let iter = BitmapIter::<u128, _>::new([0b10, 0b10, 0b11]);
259        assert_eq!(&iter.collect::<Vec<_>>(), &[1, 129, 256, 257]);
260    }
261}