bit_iter/lib.rs
1//! Iterate over the bits set in a word.
2//!
3//! A `BitIter` may be constructed from any integral value.
4//!
5//! A `BitIter` may be constructed from any integral value, and returns the positions of the `1`
6//! bits in ascending order.
7//!
8//! `BitIter` implements `DoubleEndedIterator`, so you can iterate over the positions of the set
9//! bits in descending order too.
10//!
11//! ## Example
12//!
13//! ```rust
14//! # use bit_iter::*;
15//! let x : u32 = 0x10001;
16//!
17//! for b in BitIter::from(x) {
18//! println!("Bit {} is set.", b);
19//! }
20//!
21//! println!("In reverse order:");
22//!
23//! for b in BitIter::from(x).rev() {
24//! println!("Bit {} is set.", b);
25//! }
26//! ```
27//!
28//! Output:
29//!
30//! ```text
31//! Bit 0 is set.
32//! Bit 16 is set.
33//! In reverse order:
34//! Bit 16 is set.
35//! Bit 0 is set.
36//! ```
37
38#![no_std]
39#![doc(html_root_url = "https://docs.rs/bit-iter/1.3.1")]
40
41use core::iter::{ExactSizeIterator, FusedIterator};
42
43#[cfg(test)]
44mod tests;
45
46/// An iterator which returns the positions of the set bits in a word, in ascending order.
47///
48/// ## Examples
49///
50/// Construct a `BitIter` from an integer:
51///
52/// ```rust
53/// # use bit_iter::*;
54/// let mut iter = BitIter::from(0b10000001);
55/// assert_eq!(iter.next(), Some(0usize));
56/// assert_eq!(iter.next(), Some(7usize));
57/// assert_eq!(iter.next(), None);
58/// ```
59///
60/// Iterate over the bits in an integer in ascending order:
61///
62/// ```rust
63/// # use bit_iter::*;
64/// let v : Vec<usize> = BitIter::from(0b10000001).collect();
65/// assert_eq!(v, vec![0, 7]);
66/// ```
67///
68/// `BitIter` implements `DoubleEndedIterator`, so you can also get the set bit positions in
69/// descending order:
70///
71/// ```rust
72/// # use bit_iter::*;
73/// let v : Vec<usize> = BitIter::from(0b10000001).rev().collect();
74/// assert_eq!(v, vec![7, 0]);
75/// ```
76#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
77pub struct BitIter<T>(T);
78
79macro_rules! iter_impl {
80 ($($t:ty)*) => {$(
81 #[doc(hidden)]
82 impl BitIter<$t> {
83 #[inline]
84 fn rightmost_one_pos(&self) -> usize {
85 self.0.trailing_zeros() as usize
86 }
87
88 #[inline]
89 fn leftmost_one_pos(&self) -> usize {
90 (<$t>::BITS - 1 - self.0.leading_zeros()) as usize
91 }
92
93 #[inline]
94 fn count_ones(&self) -> usize {
95 self.0.count_ones() as usize
96 }
97
98 #[inline]
99 fn clear_rightmost_one(&mut self) {
100 self.0 &= self.0.wrapping_sub(1);
101 }
102 }
103
104 /// `From` implementation for `BitIter`.
105 impl From<$t> for BitIter<$t> {
106 /// Construct a BitIter value.
107 #[inline]
108 fn from(value: $t) -> Self {
109 Self(value)
110 }
111 }
112
113 /// `Iterator` implementation for `BitIter`.
114 impl Iterator for BitIter<$t> {
115 type Item = usize;
116
117 #[inline]
118 fn next(&mut self) -> Option<Self::Item> {
119 if self.0 != 0 {
120 let trailing = self.rightmost_one_pos();
121 self.clear_rightmost_one();
122 Some(trailing)
123 } else {
124 None
125 }
126 }
127
128 #[inline]
129 fn size_hint(&self) -> (usize, Option<usize>) {
130 let sz = self.count_ones();
131 (sz, Some(sz))
132 }
133
134 #[inline]
135 fn count(self) -> usize {
136 self.count_ones()
137 }
138
139 #[inline]
140 fn last(self) -> Option<Self::Item> {
141 if self.0 != 0 {
142 Some(self.leftmost_one_pos())
143 } else {
144 None
145 }
146 }
147
148 #[inline]
149 fn nth(&mut self, n: usize) -> Option<Self::Item> {
150 let mut i = 0;
151 while self.0 != 0 && i < n {
152 self.clear_rightmost_one();
153 i += 1;
154 }
155 self.next()
156 }
157
158 #[inline]
159 fn fold<B, F>(mut self, init: B, mut f: F) -> B
160 where
161 F: FnMut(B, Self::Item) -> B
162 {
163 let mut accum = init;
164 while self.0 != 0 {
165 accum = f(accum, self.rightmost_one_pos());
166 self.clear_rightmost_one();
167 }
168 accum
169 }
170
171 #[inline]
172 fn max(self) -> Option<Self::Item> {
173 self.last()
174 }
175
176 #[inline]
177 fn min(self) -> Option<Self::Item> {
178 if self.0 != 0 {
179 Some(self.rightmost_one_pos())
180 } else {
181 None
182 }
183 }
184
185 fn is_sorted(self) -> bool {
186 true
187 }
188 }
189
190 /// `FusedIterator` implementation for `BitIter`.
191 impl FusedIterator for BitIter<$t> {}
192
193 /// `DoubleEndedIterator` implementation for `BitIter`.
194 impl DoubleEndedIterator for BitIter<$t> {
195 #[inline]
196 fn next_back(&mut self) -> Option<Self::Item> {
197 if self.0 != 0 {
198 let highest = self.leftmost_one_pos();
199 self.0 ^= 1 as $t << highest;
200 Some(highest)
201 } else {
202 None
203 }
204 }
205 }
206
207 /// `ExactSizeIterator` implementation for `BitIter`.
208 impl ExactSizeIterator for BitIter<$t> {
209 #[inline]
210 fn len(&self) -> usize {
211 self.count_ones()
212 }
213 }
214 )*}
215}
216
217iter_impl! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }