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