Skip to main content

winnow/binary/bits/
stream.rs

1use 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/// Bit-level stream state over a byte stream.
10#[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
107/// Iterator for [bit][crate::binary::bits] stream ([`Bits`])
108pub 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}