1#![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#[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#[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}