• 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 #[cfg(test)]
109 mod test {
110   use super::*;
111 
112   #[test]
test_take_0()113   fn test_take_0() {
114     let input = [0b00010010].as_ref();
115     let count = 0usize;
116     assert_eq!(count, 0usize);
117     let offset = 0usize;
118 
119     let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
120 
121     assert_eq!(result, Ok(((input, offset), 0)));
122   }
123 
124   #[test]
test_take_eof()125   fn test_take_eof() {
126     let input = [0b00010010].as_ref();
127 
128     let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
129 
130     assert_eq!(
131       result,
132       Err(crate::Err::Error(crate::error::Error {
133         input: (input, 8),
134         code: ErrorKind::Eof
135       }))
136     )
137   }
138 
139   #[test]
test_take_span_over_multiple_bytes()140   fn test_take_span_over_multiple_bytes() {
141     let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
142 
143     let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
144 
145     assert_eq!(
146       result,
147       Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
148     );
149   }
150 }
151