1use crate::bit_chunk_iterator::{UnalignedBitChunk, UnalignedBitChunkIterator};
21use crate::bit_util::{ceil, get_bit_raw};
22
23pub struct BitIterator<'a> {
27 buffer: &'a [u8],
28 current_offset: usize,
29 end_offset: usize,
30}
31
32impl<'a> BitIterator<'a> {
33 pub fn new(buffer: &'a [u8], offset: usize, len: usize) -> Self {
40 let end_offset = offset.checked_add(len).unwrap();
41 let required_len = ceil(end_offset, 8);
42 assert!(
43 buffer.len() >= required_len,
44 "BitIterator buffer too small, expected {required_len} got {}",
45 buffer.len()
46 );
47
48 Self {
49 buffer,
50 current_offset: offset,
51 end_offset,
52 }
53 }
54}
55
56impl Iterator for BitIterator<'_> {
57 type Item = bool;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 if self.current_offset == self.end_offset {
61 return None;
62 }
63 let v = unsafe { get_bit_raw(self.buffer.as_ptr(), self.current_offset) };
66 self.current_offset += 1;
67 Some(v)
68 }
69
70 fn size_hint(&self) -> (usize, Option<usize>) {
71 let remaining_bits = self.end_offset - self.current_offset;
72 (remaining_bits, Some(remaining_bits))
73 }
74}
75
76impl ExactSizeIterator for BitIterator<'_> {}
77
78impl DoubleEndedIterator for BitIterator<'_> {
79 fn next_back(&mut self) -> Option<Self::Item> {
80 if self.current_offset == self.end_offset {
81 return None;
82 }
83 self.end_offset -= 1;
84 let v = unsafe { get_bit_raw(self.buffer.as_ptr(), self.end_offset) };
87 Some(v)
88 }
89}
90
91#[derive(Debug)]
99pub struct BitSliceIterator<'a> {
100 iter: UnalignedBitChunkIterator<'a>,
101 len: usize,
102 current_offset: i64,
103 current_chunk: u64,
104}
105
106impl<'a> BitSliceIterator<'a> {
107 pub fn new(buffer: &'a [u8], offset: usize, len: usize) -> Self {
110 let chunk = UnalignedBitChunk::new(buffer, offset, len);
111 let mut iter = chunk.iter();
112
113 let current_offset = -(chunk.lead_padding() as i64);
114 let current_chunk = iter.next().unwrap_or(0);
115
116 Self {
117 iter,
118 len,
119 current_offset,
120 current_chunk,
121 }
122 }
123
124 fn advance_to_set_bit(&mut self) -> Option<(i64, u32)> {
130 loop {
131 if self.current_chunk != 0 {
132 let bit_pos = self.current_chunk.trailing_zeros();
134 return Some((self.current_offset, bit_pos));
135 }
136
137 self.current_chunk = self.iter.next()?;
138 self.current_offset += 64;
139 }
140 }
141}
142
143impl Iterator for BitSliceIterator<'_> {
144 type Item = (usize, usize);
145
146 fn next(&mut self) -> Option<Self::Item> {
147 if self.len == 0 {
149 return None;
150 }
151
152 let (start_chunk, start_bit) = self.advance_to_set_bit()?;
153
154 self.current_chunk |= (1 << start_bit) - 1;
156
157 loop {
158 if self.current_chunk != u64::MAX {
159 let end_bit = self.current_chunk.trailing_ones();
161
162 self.current_chunk &= !((1 << end_bit) - 1);
164
165 return Some((
166 (start_chunk + start_bit as i64) as usize,
167 (self.current_offset + end_bit as i64) as usize,
168 ));
169 }
170
171 match self.iter.next() {
172 Some(next) => {
173 self.current_chunk = next;
174 self.current_offset += 64;
175 }
176 None => {
177 return Some((
178 (start_chunk + start_bit as i64) as usize,
179 std::mem::replace(&mut self.len, 0),
180 ));
181 }
182 }
183 }
184 }
185}
186
187#[derive(Debug)]
192pub struct BitIndexIterator<'a> {
193 current_chunk: u64,
194 chunk_offset: i64,
195 iter: UnalignedBitChunkIterator<'a>,
196}
197
198impl<'a> BitIndexIterator<'a> {
199 pub fn new(buffer: &'a [u8], offset: usize, len: usize) -> Self {
202 let chunks = UnalignedBitChunk::new(buffer, offset, len);
203 let mut iter = chunks.iter();
204
205 let current_chunk = iter.next().unwrap_or(0);
206 let chunk_offset = -(chunks.lead_padding() as i64);
207
208 Self {
209 current_chunk,
210 chunk_offset,
211 iter,
212 }
213 }
214}
215
216impl Iterator for BitIndexIterator<'_> {
217 type Item = usize;
218
219 #[inline]
220 fn next(&mut self) -> Option<Self::Item> {
221 loop {
222 if self.current_chunk != 0 {
223 let bit_pos = self.current_chunk.trailing_zeros();
224 self.current_chunk ^= 1 << bit_pos;
225 return Some((self.chunk_offset + bit_pos as i64) as usize);
226 }
227
228 self.current_chunk = self.iter.next()?;
229 self.chunk_offset += 64;
230 }
231 }
232}
233
234#[inline]
250pub fn try_for_each_valid_idx<E, F: FnMut(usize) -> Result<(), E>>(
251 len: usize,
252 offset: usize,
253 null_count: usize,
254 nulls: Option<&[u8]>,
255 f: F,
256) -> Result<(), E> {
257 let valid_count = len - null_count;
258
259 if valid_count == len {
260 (0..len).try_for_each(f)
261 } else if null_count != len {
262 BitIndexIterator::new(nulls.unwrap(), offset, len).try_for_each(f)
263 } else {
264 Ok(())
265 }
266}
267
268#[cfg(test)]
271mod tests {
272 use super::*;
273
274 #[test]
275 fn test_bit_iterator_size_hint() {
276 let mut b = BitIterator::new(&[0b00000011], 0, 2);
277 assert_eq!(
278 b.size_hint(),
279 (2, Some(2)),
280 "Expected size_hint to be (2, Some(2))"
281 );
282
283 b.next();
284 assert_eq!(
285 b.size_hint(),
286 (1, Some(1)),
287 "Expected size_hint to be (1, Some(1)) after one bit consumed"
288 );
289
290 b.next();
291 assert_eq!(
292 b.size_hint(),
293 (0, Some(0)),
294 "Expected size_hint to be (0, Some(0)) after all bits consumed"
295 );
296 }
297
298 #[test]
299 fn test_bit_iterator() {
300 let mask = &[0b00010010, 0b00100011, 0b00000101, 0b00010001, 0b10010011];
301 let actual: Vec<_> = BitIterator::new(mask, 0, 5).collect();
302 assert_eq!(actual, &[false, true, false, false, true]);
303
304 let actual: Vec<_> = BitIterator::new(mask, 4, 5).collect();
305 assert_eq!(actual, &[true, false, false, false, true]);
306
307 let actual: Vec<_> = BitIterator::new(mask, 12, 14).collect();
308 assert_eq!(
309 actual,
310 &[
311 false, true, false, false, true, false, true, false, false, false, false, false,
312 true, false
313 ]
314 );
315
316 assert_eq!(BitIterator::new(mask, 0, 0).count(), 0);
317 assert_eq!(BitIterator::new(mask, 40, 0).count(), 0);
318 }
319
320 #[test]
321 #[should_panic(expected = "BitIterator buffer too small, expected 3 got 2")]
322 fn test_bit_iterator_bounds() {
323 let mask = &[223, 23];
324 BitIterator::new(mask, 17, 0);
325 }
326}