nom/bits/
complete.rs

1//! Bit level parsers
2//!
3
4use crate::error::{ErrorKind, ParseError};
5use crate::internal::{Err, IResult};
6use crate::lib::std::ops::{AddAssign, Div, Shl, Shr};
7use crate::traits::{Input, ToUsize};
8
9/// Generates a parser taking `count` bits
10///
11/// # Example
12/// ```rust
13/// # use nom::bits::complete::take;
14/// # use nom::IResult;
15/// # use nom::error::{Error, ErrorKind};
16/// // Input is a tuple of (input: I, bit_offset: usize)
17/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
18///  take(count)(input)
19/// }
20///
21/// // Consumes 0 bits, returns 0
22/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
23///
24/// // Consumes 4 bits, returns their values and increase offset to 4
25/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
26///
27/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
28/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
29///
30/// // Tries to consume 12 bits but only 8 are available
31/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
32/// ```
33pub fn take<I, O, C, E: ParseError<(I, usize)>>(
34  count: C,
35) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
36where
37  I: Input<Item = u8>,
38  C: ToUsize,
39  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
40{
41  let count = count.to_usize();
42  move |(input, bit_offset): (I, usize)| {
43    if count == 0 {
44      Ok(((input, bit_offset), 0u8.into()))
45    } else if input.input_len() * 8 < count + bit_offset {
46      Err(Err::Error(E::from_error_kind(
47        (input, bit_offset),
48        ErrorKind::Eof,
49      )))
50    } else {
51      let cnt = (count + bit_offset).div(8);
52      let mut acc: O = 0_u8.into();
53      let mut offset: usize = bit_offset;
54      let mut remaining: usize = count;
55      let mut end_offset: usize = 0;
56
57      for byte in input.iter_elements().take(cnt + 1) {
58        if remaining == 0 {
59          break;
60        }
61        let val: O = if offset == 0 {
62          byte.into()
63        } else {
64          ((byte << offset) >> offset).into()
65        };
66
67        if remaining < 8 - offset {
68          acc += val >> (8 - offset - remaining);
69          end_offset = remaining + offset;
70          break;
71        } else {
72          acc += val << (remaining - (8 - offset));
73          remaining -= 8 - offset;
74          offset = 0;
75        }
76      }
77      Ok(((input.take_from(cnt), end_offset), acc))
78    }
79  }
80}
81
82/// Generates a parser taking `count` bits and comparing them to `pattern`
83pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
84  pattern: O,
85  count: C,
86) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
87where
88  I: Input<Item = u8> + Clone,
89  C: ToUsize,
90  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
91{
92  let count = count.to_usize();
93  move |input: (I, usize)| {
94    let inp = input.clone();
95
96    take(count)(input).and_then(|(i, o)| {
97      if pattern == o {
98        Ok((i, o))
99      } else {
100        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
101      }
102    })
103  }
104}
105
106/// Parses one specific bit as a bool.
107///
108/// # Example
109/// ```rust
110/// # use nom::bits::complete::bool;
111/// # use nom::IResult;
112/// # use nom::error::{Error, ErrorKind};
113///
114/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
115///     bool(input)
116/// }
117///
118/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
119/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
120/// ```
121pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
122where
123  I: Input<Item = u8>,
124{
125  let (res, bit): (_, u32) = take(1usize)(input)?;
126  Ok((res, bit != 0))
127}
128
129#[cfg(test)]
130mod test {
131  use super::*;
132
133  #[test]
134  fn test_take_0() {
135    let input = [0b00010010].as_ref();
136    let count = 0usize;
137    assert_eq!(count, 0usize);
138    let offset = 0usize;
139
140    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
141
142    assert_eq!(result, Ok(((input, offset), 0)));
143  }
144
145  #[test]
146  fn test_take_eof() {
147    let input = [0b00010010].as_ref();
148
149    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
150
151    assert_eq!(
152      result,
153      Err(crate::Err::Error(crate::error::Error {
154        input: (input, 8),
155        code: ErrorKind::Eof
156      }))
157    )
158  }
159
160  #[test]
161  fn test_take_span_over_multiple_bytes() {
162    let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
163
164    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
165
166    assert_eq!(
167      result,
168      Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
169    );
170  }
171
172  #[test]
173  fn test_bool_0() {
174    let input = [0b10000000].as_ref();
175
176    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
177
178    assert_eq!(result, Ok(((input, 1), true)));
179  }
180
181  #[test]
182  fn test_bool_eof() {
183    let input = [0b10000000].as_ref();
184
185    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
186
187    assert_eq!(
188      result,
189      Err(crate::Err::Error(crate::error::Error {
190        input: (input, 8),
191        code: ErrorKind::Eof
192      }))
193    );
194  }
195}