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, RangeFrom, Shl, Shr};
7use crate::traits::{InputIter, InputLength, Slice, 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: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
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 {
46      let cnt = (count + bit_offset).div(8);
47      if input.input_len() * 8 < count + bit_offset {
48        Err(Err::Error(E::from_error_kind(
49          (input, bit_offset),
50          ErrorKind::Eof,
51        )))
52      } else {
53        let mut acc: O = 0_u8.into();
54        let mut offset: usize = bit_offset;
55        let mut remaining: usize = count;
56        let mut end_offset: usize = 0;
57
58        for byte in input.iter_elements().take(cnt + 1) {
59          if remaining == 0 {
60            break;
61          }
62          let val: O = if offset == 0 {
63            byte.into()
64          } else {
65            ((byte << offset) as u8 >> offset).into()
66          };
67
68          if remaining < 8 - offset {
69            acc += val >> (8 - offset - remaining);
70            end_offset = remaining + offset;
71            break;
72          } else {
73            acc += val << (remaining - (8 - offset));
74            remaining -= 8 - offset;
75            offset = 0;
76          }
77        }
78        Ok(((input.slice(cnt..), end_offset), acc))
79      }
80    }
81  }
82}
83
84/// Generates a parser taking `count` bits and comparing them to `pattern`
85pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
86  pattern: O,
87  count: C,
88) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
89where
90  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
91  C: ToUsize,
92  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
93{
94  let count = count.to_usize();
95  move |input: (I, usize)| {
96    let inp = input.clone();
97
98    take(count)(input).and_then(|(i, o)| {
99      if pattern == o {
100        Ok((i, o))
101      } else {
102        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
103      }
104    })
105  }
106}
107
108/// Parses one specific bit as a bool.
109///
110/// # Example
111/// ```rust
112/// # use nom::bits::complete::bool;
113/// # use nom::IResult;
114/// # use nom::error::{Error, ErrorKind};
115///
116/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
117///     bool(input)
118/// }
119///
120/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
121/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
122/// ```
123pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
124where
125  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
126{
127  let (res, bit): (_, u32) = take(1usize)(input)?;
128  Ok((res, bit != 0))
129}
130
131#[cfg(test)]
132mod test {
133  use super::*;
134
135  #[test]
136  fn test_take_0() {
137    let input = [0b00010010].as_ref();
138    let count = 0usize;
139    assert_eq!(count, 0usize);
140    let offset = 0usize;
141
142    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
143
144    assert_eq!(result, Ok(((input, offset), 0)));
145  }
146
147  #[test]
148  fn test_take_eof() {
149    let input = [0b00010010].as_ref();
150
151    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
152
153    assert_eq!(
154      result,
155      Err(crate::Err::Error(crate::error::Error {
156        input: (input, 8),
157        code: ErrorKind::Eof
158      }))
159    )
160  }
161
162  #[test]
163  fn test_take_span_over_multiple_bytes() {
164    let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
165
166    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
167
168    assert_eq!(
169      result,
170      Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
171    );
172  }
173
174  #[test]
175  fn test_bool_0() {
176    let input = [0b10000000].as_ref();
177
178    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
179
180    assert_eq!(result, Ok(((input, 1), true)));
181  }
182
183  #[test]
184  fn test_bool_eof() {
185    let input = [0b10000000].as_ref();
186
187    let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
188
189    assert_eq!(
190      result,
191      Err(crate::Err::Error(crate::error::Error {
192        input: (input, 8),
193        code: ErrorKind::Eof
194      }))
195    );
196  }
197}