winnow/binary/bits/
stream.rs1use core::num::NonZeroUsize;
2
3use crate::error::Needed;
4#[cfg(feature = "unstable-recover")]
5#[cfg(feature = "std")]
6use crate::stream::Recover;
7use crate::stream::{Checkpoint, Offset, Stream, StreamIsPartial};
8
9#[derive(Copy, Clone, Debug, PartialEq, Eq)]
11pub struct Bits<I>(pub I, pub usize);
12
13impl<I> Stream for Bits<I>
14where
15 I: Stream<Token = u8> + Clone,
16{
17 type Token = bool;
18 type Slice = (I::Slice, usize, usize);
19
20 type IterOffsets = BitOffsets<I>;
21 type Checkpoint = Checkpoint<Bits<I::Checkpoint>, Self>;
22
23 #[inline(always)]
24 fn iter_offsets(&self) -> Self::IterOffsets {
25 BitOffsets {
26 i: self.clone(),
27 o: 0,
28 }
29 }
30
31 #[inline(always)]
32 fn eof_offset(&self) -> usize {
33 let offset = self.0.eof_offset() * 8;
34 if offset == 0 {
35 0
36 } else {
37 offset - self.1
38 }
39 }
40
41 #[inline(always)]
42 fn next_token(&mut self) -> Option<Self::Token> {
43 next_bit(self)
44 }
45
46 #[inline(always)]
47 fn peek_token(&self) -> Option<Self::Token> {
48 peek_bit(self)
49 }
50
51 #[inline(always)]
52 fn offset_for<P>(&self, predicate: P) -> Option<usize>
53 where
54 P: Fn(Self::Token) -> bool,
55 {
56 self.iter_offsets()
57 .find_map(|(o, b)| predicate(b).then_some(o))
58 }
59
60 #[inline(always)]
61 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
62 if let Some(needed) = tokens
63 .checked_sub(self.eof_offset())
64 .and_then(NonZeroUsize::new)
65 {
66 Err(Needed::Size(needed))
67 } else {
68 Ok(tokens)
69 }
70 }
71
72 #[inline(always)]
73 fn next_slice(&mut self, offset: usize) -> Self::Slice {
74 let byte_offset = (offset + self.1) / 8;
75 let end_offset = (offset + self.1) % 8;
76 let s = self.0.next_slice(byte_offset);
77 let start_offset = self.1;
78 self.1 = end_offset;
79 (s, start_offset, end_offset)
80 }
81
82 #[inline(always)]
83 fn peek_slice(&self, offset: usize) -> Self::Slice {
84 let byte_offset = (offset + self.1) / 8;
85 let end_offset = (offset + self.1) % 8;
86 let s = self.0.peek_slice(byte_offset);
87 let start_offset = self.1;
88 (s, start_offset, end_offset)
89 }
90
91 #[inline(always)]
92 fn checkpoint(&self) -> Self::Checkpoint {
93 Checkpoint::<_, Self>::new(Bits(self.0.checkpoint(), self.1))
94 }
95
96 #[inline(always)]
97 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
98 self.0.reset(&checkpoint.inner.0);
99 self.1 = checkpoint.inner.1;
100 }
101
102 fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
103 write!(f, "{self:#?}")
104 }
105}
106
107pub struct BitOffsets<I> {
109 i: Bits<I>,
110 o: usize,
111}
112
113impl<I> Iterator for BitOffsets<I>
114where
115 I: Stream<Token = u8> + Clone,
116{
117 type Item = (usize, bool);
118
119 fn next(&mut self) -> Option<Self::Item> {
120 let b = next_bit(&mut self.i)?;
121 let o = self.o;
122 self.o += 1;
123 Some((o, b))
124 }
125}
126
127fn next_bit<I>(i: &mut Bits<I>) -> Option<bool>
128where
129 I: Stream<Token = u8> + Clone,
130{
131 if i.eof_offset() == 0 {
132 return None;
133 }
134
135 let offset = i.1;
136 let mut next_i = i.0.clone();
137 let byte = next_i.next_token()?;
138 let bit = (byte >> offset) & 0x1 == 0x1;
139
140 let next_offset = offset + 1;
141 if next_offset == 8 {
142 i.0 = next_i;
143 i.1 = 0;
144 } else {
145 i.1 = next_offset;
146 }
147 Some(bit)
148}
149
150fn peek_bit<I>(i: &Bits<I>) -> Option<bool>
151where
152 I: Stream<Token = u8> + Clone,
153{
154 if i.eof_offset() == 0 {
155 return None;
156 }
157
158 let offset = i.1;
159 let mut next_i = i.0.clone();
160 let byte = next_i.next_token()?;
161 Some((byte >> offset) & 0x1 == 0x1)
162}
163
164#[cfg(feature = "unstable-recover")]
165#[cfg(feature = "std")]
166impl<I, E> Recover<E> for Bits<I>
167where
168 I: Recover<E>,
169 I: Stream<Token = u8> + Clone,
170{
171 #[inline(always)]
172 fn record_err(
173 &mut self,
174 _token_start: &Self::Checkpoint,
175 _err_start: &Self::Checkpoint,
176 err: E,
177 ) -> Result<(), E> {
178 Err(err)
179 }
180
181 #[inline(always)]
182 fn is_recovery_supported() -> bool {
183 false
184 }
185}
186
187impl<I> StreamIsPartial for Bits<I>
188where
189 I: StreamIsPartial,
190{
191 type PartialState = I::PartialState;
192
193 #[inline]
194 fn complete(&mut self) -> Self::PartialState {
195 self.0.complete()
196 }
197
198 #[inline]
199 fn restore_partial(&mut self, state: Self::PartialState) {
200 self.0.restore_partial(state);
201 }
202
203 #[inline(always)]
204 fn is_partial_supported() -> bool {
205 I::is_partial_supported()
206 }
207
208 #[inline(always)]
209 fn is_partial(&self) -> bool {
210 self.0.is_partial()
211 }
212}
213
214impl<I> Offset for Bits<I>
215where
216 I: Offset,
217{
218 #[inline(always)]
219 fn offset_from(&self, start: &Self) -> usize {
220 self.0.offset_from(&start.0) * 8 + self.1 - start.1
221 }
222}
223
224impl<I> Offset<<Bits<I> as Stream>::Checkpoint> for Bits<I>
225where
226 I: Stream<Token = u8> + Clone,
227{
228 #[inline(always)]
229 fn offset_from(&self, other: &<Bits<I> as Stream>::Checkpoint) -> usize {
230 self.checkpoint().offset_from(other)
231 }
232}
233
234impl<I: Clone> crate::error::ErrorConvert<crate::error::InputError<Bits<I>>>
235 for crate::error::InputError<I>
236{
237 #[inline]
238 fn convert(self) -> crate::error::InputError<Bits<I>> {
239 self.map_input(|i| Bits(i, 0))
240 }
241}
242
243impl<I: Clone> crate::error::ErrorConvert<crate::error::InputError<I>>
244 for crate::error::InputError<Bits<I>>
245{
246 #[inline]
247 fn convert(self) -> crate::error::InputError<I> {
248 self.map_input(|Bits(i, _o)| i)
249 }
250}