1//! Bit level parsers
2//!
3
4use crate::error::{ErrorKind, ParseError};
5use crate::internal::{Err, IResult, Needed};
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
10pub fn take<I, O, C, E: ParseError<(I, usize)>>(
11 count: C,
12) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
13where
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`
59pub 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>
63where
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: usize = count.to_usize();
69 move |input: (I, usize)| {
70 let inp: (I, usize) = input.clone();
71
72 take(count)(input).and_then(|(i: (I, usize), o: 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/// ```
97pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
98where
99 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
100{
101 let (res: (I, usize), bit: u32): (_, u32) = take(count:1usize)(input)?;
102 Ok((res, bit != 0))
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108
109 #[test]
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]
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]
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]
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]
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