polars_arrow/types/
bit_chunk.rs1use std::fmt::Binary;
2use std::ops::{BitAndAssign, Not, Shl, ShlAssign, ShrAssign};
3
4use num_traits::PrimInt;
5
6use super::NativeType;
7
8pub trait BitChunk:
13 super::private::Sealed
14 + PrimInt
15 + NativeType
16 + Binary
17 + ShlAssign
18 + Not<Output = Self>
19 + ShrAssign<usize>
20 + ShlAssign<usize>
21 + Shl<usize, Output = Self>
22 + BitAndAssign
23{
24 fn to_ne_bytes(self) -> Self::Bytes;
26 fn from_ne_bytes(v: Self::Bytes) -> Self;
28}
29
30macro_rules! bit_chunk {
31 ($ty:ty) => {
32 impl BitChunk for $ty {
33 #[inline(always)]
34 fn to_ne_bytes(self) -> Self::Bytes {
35 self.to_ne_bytes()
36 }
37
38 #[inline(always)]
39 fn from_ne_bytes(v: Self::Bytes) -> Self {
40 Self::from_ne_bytes(v)
41 }
42 }
43 };
44}
45
46bit_chunk!(u8);
47bit_chunk!(u16);
48bit_chunk!(u32);
49bit_chunk!(u64);
50
51pub 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 <= 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 pub fn from_known_count(value: T, remaining: usize) -> Self {
135 Self { value, remaining }
136 }
137}
138
139impl<T: BitChunk> Iterator for BitChunkOnes<T> {
140 type Item = usize;
141
142 #[inline]
143 fn next(&mut self) -> Option<Self::Item> {
144 if self.remaining == 0 {
145 return None;
146 }
147 let v = self.value.trailing_zeros() as usize;
148 self.value &= self.value - T::one();
149
150 self.remaining -= 1;
151 Some(v)
152 }
153
154 #[inline]
155 fn size_hint(&self) -> (usize, Option<usize>) {
156 (self.remaining, Some(self.remaining))
157 }
158}
159
160unsafe impl<T: BitChunk> crate::trusted_len::TrustedLen for BitChunkOnes<T> {}