arrow2/types/
bit_chunk.rs1use std::{
2 fmt::Binary,
3 ops::{BitAndAssign, Not, Shl, ShlAssign, ShrAssign},
4};
5
6use num_traits::PrimInt;
7
8use super::NativeType;
9
10pub trait BitChunk:
15 super::private::Sealed
16 + PrimInt
17 + NativeType
18 + Binary
19 + ShlAssign
20 + Not<Output = Self>
21 + ShrAssign<usize>
22 + ShlAssign<usize>
23 + Shl<usize, Output = Self>
24 + BitAndAssign
25{
26 fn to_ne_bytes(self) -> Self::Bytes;
28 fn from_ne_bytes(v: Self::Bytes) -> Self;
30}
31
32macro_rules! bit_chunk {
33 ($ty:ty) => {
34 impl BitChunk for $ty {
35 #[inline(always)]
36 fn to_ne_bytes(self) -> Self::Bytes {
37 self.to_ne_bytes()
38 }
39
40 #[inline(always)]
41 fn from_ne_bytes(v: Self::Bytes) -> Self {
42 Self::from_ne_bytes(v)
43 }
44 }
45 };
46}
47
48bit_chunk!(u8);
49bit_chunk!(u16);
50bit_chunk!(u32);
51bit_chunk!(u64);
52
53pub struct BitChunkIter<T: BitChunk> {
66 value: T,
67 mask: T,
68 remaining: usize,
69}
70
71impl<T: BitChunk> BitChunkIter<T> {
72 #[inline]
74 pub fn new(value: T, len: usize) -> Self {
75 assert!(len <= std::mem::size_of::<T>() * 8);
76 Self {
77 value,
78 remaining: len,
79 mask: T::one(),
80 }
81 }
82}
83
84impl<T: BitChunk> Iterator for BitChunkIter<T> {
85 type Item = bool;
86
87 #[inline]
88 fn next(&mut self) -> Option<Self::Item> {
89 if self.remaining == 0 {
90 return None;
91 };
92 let result = Some(self.value & self.mask != T::zero());
93 self.remaining -= 1;
94 self.mask <<= 1;
95 result
96 }
97
98 #[inline]
99 fn size_hint(&self) -> (usize, Option<usize>) {
100 (self.remaining, Some(self.remaining))
101 }
102}
103
104unsafe impl<T: BitChunk> crate::trusted_len::TrustedLen for BitChunkIter<T> {}
107
108pub struct BitChunkOnes<T: BitChunk> {
119 value: T,
120 remaining: usize,
121}
122
123impl<T: BitChunk> BitChunkOnes<T> {
124 #[inline]
126 pub fn new(value: T) -> Self {
127 Self {
128 value,
129 remaining: value.count_ones() as usize,
130 }
131 }
132
133 #[inline]
134 #[cfg(feature = "compute_filter")]
135 pub(crate) fn from_known_count(value: T, remaining: usize) -> Self {
136 Self { value, remaining }
137 }
138}
139
140impl<T: BitChunk> Iterator for BitChunkOnes<T> {
141 type Item = usize;
142
143 #[inline]
144 fn next(&mut self) -> Option<Self::Item> {
145 if self.remaining == 0 {
146 return None;
147 }
148 let v = self.value.trailing_zeros() as usize;
149 self.value &= self.value - T::one();
150
151 self.remaining -= 1;
152 Some(v)
153 }
154
155 #[inline]
156 fn size_hint(&self) -> (usize, Option<usize>) {
157 (self.remaining, Some(self.remaining))
158 }
159}
160
161unsafe impl<T: BitChunk> crate::trusted_len::TrustedLen for BitChunkOnes<T> {}