• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Bit level parsers
2 //!
3 
4 use crate::error::{ErrorKind, ParseError};
5 use crate::internal::{Err, IResult};
6 use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
7 use 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 /// ```
take<I, O, C, E: ParseError<(I, usize)>>( count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength, C: ToUsize, O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,33 pub fn take<I, O, C, E: ParseError<(I, usize)>>(
34   count: C,
35 ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
36 where
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`
tag<I, O, C, E: ParseError<(I, usize)>>( pattern: O, count: C, ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E> where I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone, C: ToUsize, O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,85 pub 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>
89 where
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 /// ```
bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E> where I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,123 pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
124 where
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)]
132 mod test {
133   use super::*;
134 
135   #[test]
test_take_0()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]
test_take_eof()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]
test_take_span_over_multiple_bytes()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]
test_bool_0()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]
test_bool_eof()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 }
198