1use 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
9pub 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
84pub 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
108pub 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}