1 //! Bit level parsers
2 //!
3 
4 use crate::error::{ErrorKind, ParseError};
5 use crate::internal::{Err, IResult, Needed};
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
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>,10 pub fn take<I, O, C, E: ParseError<(I, usize)>>(
11   count: C,
12 ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
13 where
14   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
15   C: ToUsize,
16   O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
17 {
18   let count = count.to_usize();
19   move |(input, bit_offset): (I, usize)| {
20     if count == 0 {
21       Ok(((input, bit_offset), 0u8.into()))
22     } else {
23       let cnt = (count + bit_offset).div(8);
24       if input.input_len() * 8 < count + bit_offset {
25         Err(Err::Incomplete(Needed::new(count as usize)))
26       } else {
27         let mut acc: O = 0_u8.into();
28         let mut offset: usize = bit_offset;
29         let mut remaining: usize = count;
30         let mut end_offset: usize = 0;
31 
32         for byte in input.iter_elements().take(cnt + 1) {
33           if remaining == 0 {
34             break;
35           }
36           let val: O = if offset == 0 {
37             byte.into()
38           } else {
39             ((byte << offset) as u8 >> offset).into()
40           };
41 
42           if remaining < 8 - offset {
43             acc += val >> (8 - offset - remaining);
44             end_offset = remaining + offset;
45             break;
46           } else {
47             acc += val << (remaining - (8 - offset));
48             remaining -= 8 - offset;
49             offset = 0;
50           }
51         }
52         Ok(((input.slice(cnt..), end_offset), acc))
53       }
54     }
55   }
56 }
57 
58 /// 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,59 pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
60   pattern: O,
61   count: C,
62 ) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
63 where
64   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
65   C: ToUsize,
66   O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
67 {
68   let count = count.to_usize();
69   move |input: (I, usize)| {
70     let inp = input.clone();
71 
72     take(count)(input).and_then(|(i, o)| {
73       if pattern == o {
74         Ok((i, o))
75       } else {
76         Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
77       }
78     })
79   }
80 }
81 
82 /// Parses one specific bit as a bool.
83 ///
84 /// # Example
85 /// ```rust
86 /// # use nom::bits::complete::bool;
87 /// # use nom::IResult;
88 /// # use nom::error::{Error, ErrorKind};
89 ///
90 /// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
91 ///     bool(input)
92 /// }
93 ///
94 /// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
95 /// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
96 /// ```
bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E> where I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,97 pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
98 where
99   I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
100 {
101   let (res, bit): (_, u32) = take(1usize)(input)?;
102   Ok((res, bit != 0))
103 }
104 
105 #[cfg(test)]
106 mod test {
107   use super::*;
108 
109   #[test]
test_take_0()110   fn test_take_0() {
111     let input = [].as_ref();
112     let count = 0usize;
113     assert_eq!(count, 0usize);
114     let offset = 0usize;
115 
116     let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
117 
118     assert_eq!(result, Ok(((input, offset), 0)));
119   }
120 
121   #[test]
test_tag_ok()122   fn test_tag_ok() {
123     let input = [0b00011111].as_ref();
124     let offset = 0usize;
125     let bits_to_take = 4usize;
126     let value_to_tag = 0b0001;
127 
128     let result: crate::IResult<(&[u8], usize), usize> =
129       tag(value_to_tag, bits_to_take)((input, offset));
130 
131     assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
132   }
133 
134   #[test]
test_tag_err()135   fn test_tag_err() {
136     let input = [0b00011111].as_ref();
137     let offset = 0usize;
138     let bits_to_take = 4usize;
139     let value_to_tag = 0b1111;
140 
141     let result: crate::IResult<(&[u8], usize), usize> =
142       tag(value_to_tag, bits_to_take)((input, offset));
143 
144     assert_eq!(
145       result,
146       Err(crate::Err::Error(crate::error::Error {
147         input: (input, offset),
148         code: ErrorKind::TagBits
149       }))
150     );
151   }
152 
153   #[test]
test_bool_0()154   fn test_bool_0() {
155     let input = [0b10000000].as_ref();
156 
157     let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
158 
159     assert_eq!(result, Ok(((input, 1), true)));
160   }
161 
162   #[test]
test_bool_eof()163   fn test_bool_eof() {
164     let input = [0b10000000].as_ref();
165 
166     let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
167 
168     assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
169   }
170 }
171