nom8/bits/
streaming.rs

1//! Bit level parsers
2//!
3
4#![allow(deprecated)]
5
6use crate::error::{ErrorKind, ParseError};
7use crate::input::{InputIter, InputLength, Slice, ToUsize};
8use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
9use crate::{Err, IResult, Needed};
10
11/// Generates a parser taking `count` bits
12///
13/// **WARNING:** Deprecated, replaced with [`nom8::bits::take`][crate::bits::take] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
14#[deprecated(
15  since = "8.0.0",
16  note = "Replaced with `nom8::bits::take` with input wrapped in `nom8::input::Streaming`"
17)]
18pub fn take<I, O, C, E: ParseError<(I, usize)>>(
19  count: C,
20) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
21where
22  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
23  C: ToUsize,
24  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
25{
26  let count = count.to_usize();
27  move |input: (I, usize)| take_internal(input, count)
28}
29
30pub(crate) fn take_internal<I, O, E: ParseError<(I, usize)>>(
31  (input, bit_offset): (I, usize),
32  count: usize,
33) -> IResult<(I, usize), O, E>
34where
35  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
36  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
37{
38  if count == 0 {
39    Ok(((input, bit_offset), 0u8.into()))
40  } else {
41    let cnt = (count + bit_offset).div(8);
42    if input.input_len() * 8 < count + bit_offset {
43      Err(Err::Incomplete(Needed::new(count as usize)))
44    } else {
45      let mut acc: O = 0_u8.into();
46      let mut offset: usize = bit_offset;
47      let mut remaining: usize = count;
48      let mut end_offset: usize = 0;
49
50      for byte in input.iter_elements().take(cnt + 1) {
51        if remaining == 0 {
52          break;
53        }
54        let val: O = if offset == 0 {
55          byte.into()
56        } else {
57          ((byte << offset) as u8 >> offset).into()
58        };
59
60        if remaining < 8 - offset {
61          acc += val >> (8 - offset - remaining);
62          end_offset = remaining + offset;
63          break;
64        } else {
65          acc += val << (remaining - (8 - offset));
66          remaining -= 8 - offset;
67          offset = 0;
68        }
69      }
70      Ok(((input.slice(cnt..), end_offset), acc))
71    }
72  }
73}
74
75/// Generates a parser taking `count` bits and comparing them to `pattern`
76///
77/// **WARNING:** Deprecated, replaced with [`nom8::bits::tag`][crate::bits::tag] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
78#[deprecated(
79  since = "8.0.0",
80  note = "Replaced with `nom8::bits::tag` with input wrapped in `nom8::input::Streaming`"
81)]
82pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
83  pattern: O,
84  count: C,
85) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
86where
87  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
88  C: ToUsize,
89  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
90{
91  let count = count.to_usize();
92  move |input: (I, usize)| tag_internal(input, &pattern, count)
93}
94
95pub(crate) fn tag_internal<I, O, E: ParseError<(I, usize)>>(
96  input: (I, usize),
97  pattern: &O,
98  count: usize,
99) -> IResult<(I, usize), O, E>
100where
101  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
102  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
103{
104  let inp = input.clone();
105
106  take(count)(input).and_then(|(i, o)| {
107    if *pattern == o {
108      Ok((i, o))
109    } else {
110      Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
111    }
112  })
113}
114
115#[cfg(test)]
116mod test {
117  use super::*;
118
119  #[test]
120  fn test_take_0() {
121    let input = [].as_ref();
122    let count = 0usize;
123    assert_eq!(count, 0usize);
124    let offset = 0usize;
125
126    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
127
128    assert_eq!(result, Ok(((input, offset), 0)));
129  }
130
131  #[test]
132  fn test_tag_ok() {
133    let input = [0b00011111].as_ref();
134    let offset = 0usize;
135    let bits_to_take = 4usize;
136    let value_to_tag = 0b0001;
137
138    let result: crate::IResult<(&[u8], usize), usize> =
139      tag(value_to_tag, bits_to_take)((input, offset));
140
141    assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
142  }
143
144  #[test]
145  fn test_tag_err() {
146    let input = [0b00011111].as_ref();
147    let offset = 0usize;
148    let bits_to_take = 4usize;
149    let value_to_tag = 0b1111;
150
151    let result: crate::IResult<(&[u8], usize), usize> =
152      tag(value_to_tag, bits_to_take)((input, offset));
153
154    assert_eq!(
155      result,
156      Err(crate::Err::Error(crate::error::Error {
157        input: (input, offset),
158        code: ErrorKind::TagBits
159      }))
160    );
161  }
162}