winnow/binary/bits/mod.rs
1//! Bit level parsers
2//!
3
4mod stream;
5#[cfg(test)]
6mod tests;
7
8pub use self::stream::BitOffsets;
9pub use self::stream::Bits;
10
11use crate::combinator::trace;
12use crate::error::{ErrorConvert, Needed, ParserError};
13use crate::stream::{Stream, StreamIsPartial, ToUsize};
14use crate::{Parser, Result};
15use core::ops::{AddAssign, Div, Shl, Shr};
16
17/// Number of bits in a byte
18const BYTE: usize = u8::BITS as usize;
19
20/// Converts a byte-level input to a bit-level input
21///
22/// See [`bytes`] to convert it back.
23///
24/// # Example
25/// ```rust
26/// # use winnow::prelude::*;
27/// # use winnow::Bytes;
28/// # use winnow::binary::bits::{bits, take};
29/// # use winnow::error::ContextError;
30/// # use winnow::error::ErrMode;
31/// type Stream<'i> = &'i Bytes;
32///
33/// fn stream(b: &[u8]) -> Stream<'_> {
34/// Bytes::new(b)
35/// }
36///
37/// fn parse(input: &mut Stream<'_>) -> ModalResult<(u8, u8)> {
38/// bits::<_, _, ErrMode<ContextError>, _, _>((take(4usize), take(8usize))).parse_next(input)
39/// }
40///
41/// let input = stream(&[0x12, 0x34, 0xff, 0xff]);
42///
43/// let output = parse.parse_peek(input).expect("We take 1.5 bytes and the input is longer than 2 bytes");
44///
45/// // The first byte is consumed, the second byte is partially consumed and dropped.
46/// let remaining = output.0;
47/// assert_eq!(remaining, stream(&[0xff, 0xff]));
48///
49/// let parsed = output.1;
50/// assert_eq!(parsed.0, 0x01);
51/// assert_eq!(parsed.1, 0x23);
52/// ```
53pub fn bits<Input, Output, BitError, ByteError, ParseNext>(
54 mut parser: ParseNext,
55) -> impl Parser<Input, Output, ByteError>
56where
57 BitError: ParserError<Bits<Input>> + ErrorConvert<ByteError>,
58 ByteError: ParserError<Input>,
59 Bits<Input>: Stream,
60 Input: Stream + Clone,
61 ParseNext: Parser<Bits<Input>, Output, BitError>,
62{
63 trace("bits", move |input: &mut Input| {
64 let mut bit_input = Bits(input.clone(), 0);
65 match parser.parse_next(&mut bit_input) {
66 Ok(result) => {
67 let Bits(mut rest, offset) = bit_input;
68 // If the next byte has been partially read, it will be sliced away as well.
69 // The parser functions might already slice away all fully read bytes.
70 // That's why `offset / BYTE` isn't necessarily needed at all times.
71 let remaining_bytes_index = offset / BYTE + if offset % BYTE == 0 { 0 } else { 1 };
72 let _ = rest.next_slice(remaining_bytes_index);
73 *input = rest;
74 Ok(result)
75 }
76 Err(e) => match e.needed() {
77 Some(n) => Err(ParserError::incomplete(
78 input,
79 n.map(|u| u.get() / BYTE + 1),
80 )),
81 None => Err(ErrorConvert::convert(e)),
82 },
83 }
84 })
85}
86
87/// Convert a [`bits`] stream back into a byte stream
88///
89/// <div class="warning">
90///
91/// **Warning:** A partial byte remaining in the input will be ignored and the given parser will
92/// start parsing at the next full byte.
93///
94/// </div>
95///
96/// # Examples
97///
98/// ```
99/// # use winnow::prelude::*;
100/// # use winnow::Bytes;
101/// # use winnow::token::rest;
102/// # use winnow::error::ContextError;
103/// # use winnow::error::ErrMode;
104/// use winnow::binary::bits::{bits, bytes, take};
105///
106/// type Stream<'i> = &'i Bytes;
107///
108/// fn stream(b: &[u8]) -> Stream<'_> {
109/// Bytes::new(b)
110/// }
111///
112/// fn parse<'i>(input: &mut Stream<'i>) -> ModalResult<(u8, u8, &'i [u8])> {
113/// bits::<_, _, ErrMode<ContextError>, _, _>((
114/// take(4usize),
115/// take(8usize),
116/// bytes::<_, _, ErrMode<ContextError>, _, _>(rest)
117/// )).parse_next(input)
118/// }
119///
120/// let input = stream(&[0x12, 0x34, 0xff, 0xff]);
121///
122/// assert_eq!(parse.parse_peek(input), Ok(( stream(&[]), (0x01, 0x23, &[0xff, 0xff][..]) )));
123/// ```
124pub fn bytes<Input, Output, ByteError, BitError, ParseNext>(
125 mut parser: ParseNext,
126) -> impl Parser<Bits<Input>, Output, BitError>
127where
128 ByteError: ParserError<Input> + ErrorConvert<BitError>,
129 BitError: ParserError<Bits<Input>>,
130 Input: Stream<Token = u8> + Clone,
131 ParseNext: Parser<Input, Output, ByteError>,
132{
133 trace("bytes", move |bit_input: &mut Bits<Input>| {
134 let Bits(mut input, offset) = bit_input.clone();
135 let _ = if offset % BYTE != 0 {
136 input.next_slice(1 + offset / BYTE)
137 } else {
138 input.next_slice(offset / BYTE)
139 };
140 match parser.parse_next(&mut input) {
141 Ok(res) => {
142 *bit_input = Bits(input, 0);
143 Ok(res)
144 }
145 Err(e) => match e.needed() {
146 Some(Needed::Unknown) => Err(ParserError::incomplete(bit_input, Needed::Unknown)),
147 Some(Needed::Size(sz)) => Err(match sz.get().checked_mul(BYTE) {
148 Some(v) => ParserError::incomplete(bit_input, Needed::new(v)),
149 None => ParserError::assert(
150 bit_input,
151 "overflow in turning needed bytes into needed bits",
152 ),
153 }),
154 None => Err(ErrorConvert::convert(e)),
155 },
156 }
157 })
158}
159
160/// Parse taking `count` bits
161///
162/// # Effective Signature
163///
164/// Assuming you are parsing a [`Bits<&[u8]>`][Bits] bit [Stream]:
165/// ```rust
166/// # use winnow::prelude::*;;
167/// # use winnow::error::ContextError;
168/// # use winnow::binary::bits::Bits;
169/// pub fn take<'i>(count: usize) -> impl Parser<Bits<&'i [u8]>, u8, ContextError>
170/// # {
171/// # winnow::binary::bits::take(count)
172/// # }
173/// ```
174///
175/// # Example
176/// ```rust
177/// # use winnow::prelude::*;
178/// # use winnow::Bytes;
179/// # use winnow::error::ContextError;
180/// use winnow::binary::bits::{Bits, take};
181///
182/// type Stream<'i> = &'i Bytes;
183///
184/// fn stream(b: &[u8]) -> Stream<'_> {
185/// Bytes::new(b)
186/// }
187///
188/// // Consumes 0 bits, returns 0
189/// assert_eq!(take::<_, usize, _, ContextError>(0usize).parse_peek(Bits(stream(&[0b00010010]), 0)), Ok((Bits(stream(&[0b00010010]), 0), 0)));
190///
191/// // Consumes 4 bits, returns their values and increase offset to 4
192/// assert_eq!(take::<_, usize, _, ContextError>(4usize).parse_peek(Bits(stream(&[0b00010010]), 0)), Ok((Bits(stream(&[0b00010010]), 4), 0b00000001)));
193///
194/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
195/// assert_eq!(take::<_, usize, _, ContextError>(4usize).parse_peek(Bits(stream(&[0b00010010]), 4)), Ok((Bits(stream(&[]), 0), 0b00000010)));
196///
197/// // Tries to consume 12 bits but only 8 are available
198/// assert!(take::<_, usize, _, ContextError>(12usize).parse_peek(Bits(stream(&[0b00010010]), 0)).is_err());
199/// ```
200#[inline(always)]
201pub fn take<Input, Output, Count, Error>(count: Count) -> impl Parser<Bits<Input>, Output, Error>
202where
203 Input: Stream<Token = u8> + StreamIsPartial + Clone,
204 Output: From<u8> + AddAssign + Shl<usize, Output = Output> + Shr<usize, Output = Output>,
205 Count: ToUsize,
206 Error: ParserError<Bits<Input>>,
207{
208 let count = count.to_usize();
209 trace("take", move |input: &mut Bits<Input>| {
210 if <Input as StreamIsPartial>::is_partial_supported() {
211 take_::<_, _, _, true>(input, count)
212 } else {
213 take_::<_, _, _, false>(input, count)
214 }
215 })
216}
217
218fn take_<I, O, E: ParserError<Bits<I>>, const PARTIAL: bool>(
219 bit_input: &mut Bits<I>,
220 count: usize,
221) -> Result<O, E>
222where
223 I: StreamIsPartial,
224 I: Stream<Token = u8> + Clone,
225 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
226{
227 if count == 0 {
228 Ok(0u8.into())
229 } else {
230 let Bits(mut input, bit_offset) = bit_input.clone();
231 if input.eof_offset() * BYTE < count + bit_offset {
232 if PARTIAL && input.is_partial() {
233 Err(ParserError::incomplete(bit_input, Needed::new(count)))
234 } else {
235 Err(ParserError::from_input(&Bits(input, bit_offset)))
236 }
237 } else {
238 let cnt = (count + bit_offset).div(BYTE);
239 let mut acc: O = 0_u8.into();
240 let mut offset: usize = bit_offset;
241 let mut remaining: usize = count;
242 let mut end_offset: usize = 0;
243
244 for (_, byte) in input.iter_offsets().take(cnt + 1) {
245 if remaining == 0 {
246 break;
247 }
248 let val: O = if offset == 0 {
249 byte.into()
250 } else {
251 (byte << offset >> offset).into()
252 };
253
254 if remaining < BYTE - offset {
255 acc += val >> (BYTE - offset - remaining);
256 end_offset = remaining + offset;
257 break;
258 } else {
259 acc += val << (remaining - (BYTE - offset));
260 remaining -= BYTE - offset;
261 offset = 0;
262 }
263 }
264 let _ = input.next_slice(cnt);
265 *bit_input = Bits(input, end_offset);
266 Ok(acc)
267 }
268 }
269}
270
271/// Parse taking `count` bits and comparing them to `pattern`
272///
273/// # Effective Signature
274///
275/// Assuming you are parsing a [`Bits<&[u8]>`][Bits] bit [Stream]:
276/// ```rust
277/// # use winnow::prelude::*;;
278/// # use winnow::error::ContextError;
279/// # use winnow::binary::bits::Bits;
280/// pub fn pattern<'i>(pattern: u8, count: usize) -> impl Parser<Bits<&'i [u8]>, u8, ContextError>
281/// # {
282/// # winnow::binary::bits::pattern(pattern, count)
283/// # }
284/// ```
285///
286/// # Example
287///
288/// ```rust
289/// # use winnow::prelude::*;
290/// # use winnow::Bytes;
291/// # use winnow::error::ContextError;
292/// use winnow::binary::bits::pattern;
293///
294/// type Stream<'i> = &'i Bytes;
295///
296/// fn stream(b: &[u8]) -> Stream<'_> {
297/// Bytes::new(b)
298/// }
299///
300/// /// Compare the lowest `count` bits of `input` against the lowest `count` bits of `pattern`.
301/// /// Return Ok and the matching section of `input` if there's a match.
302/// /// Return Err if there's no match.
303/// # use winnow::binary::bits::Bits;
304/// fn parser(bits: u8, count: u8, input: &mut Bits<Stream<'_>>) -> ModalResult<u8> {
305/// pattern(bits, count).parse_next(input)
306/// }
307///
308/// // The lowest 4 bits of 0b00001111 match the lowest 4 bits of 0b11111111.
309/// assert_eq!(
310/// pattern::<_, usize, _, ContextError>(0b0000_1111, 4usize).parse_peek(Bits(stream(&[0b1111_1111]), 0)),
311/// Ok((Bits(stream(&[0b1111_1111]), 4), 0b0000_1111))
312/// );
313///
314/// // The lowest bit of 0b00001111 matches the lowest bit of 0b11111111 (both are 1).
315/// assert_eq!(
316/// pattern::<_, usize, _, ContextError>(0b00000001, 1usize).parse_peek(Bits(stream(&[0b11111111]), 0)),
317/// Ok((Bits(stream(&[0b11111111]), 1), 0b00000001))
318/// );
319///
320/// // The lowest 2 bits of 0b11111111 and 0b00000001 are different.
321/// assert!(pattern::<_, usize, _, ContextError>(0b000000_01, 2usize).parse_peek(Bits(stream(&[0b111111_11]), 0)).is_err());
322///
323/// // The lowest 8 bits of 0b11111111 and 0b11111110 are different.
324/// assert!(pattern::<_, usize, _, ContextError>(0b11111110, 8usize).parse_peek(Bits(stream(&[0b11111111]), 0)).is_err());
325/// ```
326#[inline(always)]
327#[doc(alias = "literal")]
328#[doc(alias = "just")]
329#[doc(alias = "tag")]
330pub fn pattern<Input, Output, Count, Error: ParserError<Bits<Input>>>(
331 pattern: Output,
332 count: Count,
333) -> impl Parser<Bits<Input>, Output, Error>
334where
335 Input: Stream<Token = u8> + StreamIsPartial + Clone,
336 Count: ToUsize,
337 Output: From<u8>
338 + AddAssign
339 + Shl<usize, Output = Output>
340 + Shr<usize, Output = Output>
341 + PartialEq,
342{
343 let count = count.to_usize();
344 trace("pattern", move |input: &mut Bits<Input>| {
345 let start = input.checkpoint();
346
347 take(count).parse_next(input).and_then(|o| {
348 if pattern == o {
349 Ok(o)
350 } else {
351 input.reset(&start);
352 Err(ParserError::from_input(input))
353 }
354 })
355 })
356}
357
358/// Parses one specific bit as a bool.
359///
360/// # Effective Signature
361///
362/// Assuming you are parsing a [`Bits<&[u8]>`][Bits] bit [Stream]:
363/// ```rust
364/// # use winnow::prelude::*;;
365/// # use winnow::error::ContextError;
366/// # use winnow::binary::bits::Bits;
367/// pub fn bool(input: &mut Bits<&[u8]>) -> ModalResult<bool>
368/// # {
369/// # winnow::binary::bits::bool.parse_next(input)
370/// # }
371/// ```
372///
373/// # Example
374///
375/// ```rust
376/// # use winnow::prelude::*;
377/// # use winnow::Bytes;
378/// # use winnow::error::InputError;
379/// use winnow::binary::bits::bool;
380///
381/// type Stream<'i> = &'i Bytes;
382///
383/// fn stream(b: &[u8]) -> Stream<'_> {
384/// Bytes::new(b)
385/// }
386///
387/// # use winnow::binary::bits::Bits;
388/// fn parse(input: &mut Bits<Stream<'_>>) -> ModalResult<bool> {
389/// bool.parse_next(input)
390/// }
391///
392/// assert_eq!(parse.parse_peek(Bits(stream(&[0b10000000]), 0)), Ok((Bits(stream(&[0b10000000]), 1), true)));
393/// assert_eq!(parse.parse_peek(Bits(stream(&[0b10000000]), 1)), Ok((Bits(stream(&[0b10000000]), 2), false)));
394/// ```
395#[doc(alias = "any")]
396pub fn bool<Input, Error: ParserError<Bits<Input>>>(input: &mut Bits<Input>) -> Result<bool, Error>
397where
398 Input: Stream<Token = u8> + StreamIsPartial + Clone,
399{
400 trace("bool", |input: &mut Bits<Input>| {
401 let bit: u32 = take(1usize).parse_next(input)?;
402 Ok(bit != 0)
403 })
404 .parse_next(input)
405}