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, RangeFrom, Shl, Shr, Div};
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)>>(count: C) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
11 where
12 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
13 C: ToUsize,
14 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
15 {
16 let count = count.to_usize();
17 move |(input, bit_offset): (I, usize)| {
18 if count == 0 {
19 Ok(((input, bit_offset), 0u8.into()))
20 } else {
21 let cnt = (count + bit_offset).div(8);
22 if input.input_len() * 8 < count + bit_offset {
23 Err(Err::Error(E::from_error_kind((input, bit_offset), ErrorKind::Eof)))
24 } else {
25 let mut acc:O = (0 as u8).into();
26 let mut offset: usize = bit_offset;
27 let mut remaining: usize = count;
28 let mut end_offset: usize = 0;
29
30 for byte in input.iter_elements().take(cnt + 1) {
31 if remaining == 0 {
32 break;
33 }
34 let val: O = if offset == 0 {
35 byte.into()
36 } else {
37 ((byte << offset) as u8 >> offset).into()
38 };
39
40 if remaining < 8 - offset {
41 acc += val >> (8 - offset - remaining);
42 end_offset = remaining + offset;
43 break;
44 } else {
45 acc += val << (remaining - (8 - offset));
46 remaining -= 8 - offset;
47 offset = 0;
48 }
49 }
50 Ok(( (input.slice(cnt..), end_offset) , acc))
51 }
52 }
53 }
54 }
55
56 /// 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,57 pub fn tag<I, O, C, E: ParseError<(I, usize)>>(pattern: O, count: C) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
58 where
59 I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
60 C: ToUsize,
61 O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
62 {
63 let count = count.to_usize();
64 move |input: (I, usize)| {
65 let inp = input.clone();
66
67 take(count)(input).and_then(|(i, o)| {
68 if pattern == o {
69 Ok((i, o))
70 } else {
71 Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
72 }
73 })
74 }
75 }
76