1use crate::error::{ErrorKind, ParseError};
5use crate::internal::{Err, IResult};
6use crate::lib::std::ops::{AddAssign, Div, Shl, Shr};
7use crate::traits::{Input, 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: Input<Item = u8>,
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 if input.input_len() * 8 < count + bit_offset {
46 Err(Err::Error(E::from_error_kind(
47 (input, bit_offset),
48 ErrorKind::Eof,
49 )))
50 } else {
51 let cnt = (count + bit_offset).div(8);
52 let mut acc: O = 0_u8.into();
53 let mut offset: usize = bit_offset;
54 let mut remaining: usize = count;
55 let mut end_offset: usize = 0;
56
57 for byte in input.iter_elements().take(cnt + 1) {
58 if remaining == 0 {
59 break;
60 }
61 let val: O = if offset == 0 {
62 byte.into()
63 } else {
64 ((byte << offset) >> offset).into()
65 };
66
67 if remaining < 8 - offset {
68 acc += val >> (8 - offset - remaining);
69 end_offset = remaining + offset;
70 break;
71 } else {
72 acc += val << (remaining - (8 - offset));
73 remaining -= 8 - offset;
74 offset = 0;
75 }
76 }
77 Ok(((input.take_from(cnt), end_offset), acc))
78 }
79 }
80}
81
82pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
84 pattern: O,
85 count: C,
86) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
87where
88 I: Input<Item = u8> + Clone,
89 C: ToUsize,
90 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
91{
92 let count = count.to_usize();
93 move |input: (I, usize)| {
94 let inp = input.clone();
95
96 take(count)(input).and_then(|(i, o)| {
97 if pattern == o {
98 Ok((i, o))
99 } else {
100 Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
101 }
102 })
103 }
104}
105
106pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
122where
123 I: Input<Item = u8>,
124{
125 let (res, bit): (_, u32) = take(1usize)(input)?;
126 Ok((res, bit != 0))
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132
133 #[test]
134 fn test_take_0() {
135 let input = [0b00010010].as_ref();
136 let count = 0usize;
137 assert_eq!(count, 0usize);
138 let offset = 0usize;
139
140 let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
141
142 assert_eq!(result, Ok(((input, offset), 0)));
143 }
144
145 #[test]
146 fn test_take_eof() {
147 let input = [0b00010010].as_ref();
148
149 let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
150
151 assert_eq!(
152 result,
153 Err(crate::Err::Error(crate::error::Error {
154 input: (input, 8),
155 code: ErrorKind::Eof
156 }))
157 )
158 }
159
160 #[test]
161 fn test_take_span_over_multiple_bytes() {
162 let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
163
164 let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
165
166 assert_eq!(
167 result,
168 Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
169 );
170 }
171
172 #[test]
173 fn test_bool_0() {
174 let input = [0b10000000].as_ref();
175
176 let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
177
178 assert_eq!(result, Ok(((input, 1), true)));
179 }
180
181 #[test]
182 fn test_bool_eof() {
183 let input = [0b10000000].as_ref();
184
185 let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
186
187 assert_eq!(
188 result,
189 Err(crate::Err::Error(crate::error::Error {
190 input: (input, 8),
191 code: ErrorKind::Eof
192 }))
193 );
194 }
195}