1#![allow(clippy::useless_let_if_seq)]
2use std::{convert::TryFrom, str};
3
4use half::f16;
5use nom::{
6 bits::{bits, bytes},
7 branch::alt,
8 bytes::streaming::take as take_bytes,
9 combinator::{map, map_res, verify},
10 error::{make_error, ErrorKind},
11 multi::{count, many_till},
12 number::streaming::{be_f32, be_f64, be_u16},
13 sequence::{pair, preceded},
14 Err, IResult,
15};
16
17use crate::{ByteString, DataItem, FloatWidth, IntegerWidth, Result, Simple, Tag, TextString};
18
19pub fn take_bits<I, O>(count: usize) -> impl FnMut((I, usize)) -> IResult<(I, usize), O>
20where
21 I: nom::Slice<std::ops::RangeFrom<usize>> + nom::InputIter<Item = u8> + nom::InputLength,
22 O: From<u8>
23 + core::ops::AddAssign
24 + core::ops::Shl<usize, Output = O>
25 + core::ops::Shr<usize, Output = O>,
26{
27 nom::bits::streaming::take(count)
28}
29
30pub fn tag_bits<I, O>(pattern: O, count: usize) -> impl FnMut((I, usize)) -> IResult<(I, usize), O>
31where
32 I: nom::Slice<std::ops::RangeFrom<usize>>
33 + nom::InputIter<Item = u8>
34 + nom::InputLength
35 + Clone,
36 O: From<u8>
37 + core::ops::AddAssign
38 + core::ops::Shl<usize, Output = O>
39 + core::ops::Shr<usize, Output = O>
40 + PartialEq,
41{
42 nom::bits::streaming::tag(pattern, count)
43}
44
45fn integer(input: (&[u8], usize)) -> IResult<(&[u8], usize), (u64, IntegerWidth)> {
46 alt((
47 pair(verify(take_bits(5), |&v| v < 24), |i| {
48 Ok((i, IntegerWidth::Zero))
49 }),
50 pair(preceded(tag_bits(24, 5), take_bits(8)), |i| {
51 Ok((i, IntegerWidth::Eight))
52 }),
53 pair(preceded(tag_bits(25, 5), take_bits(16)), |i| {
54 Ok((i, IntegerWidth::Sixteen))
55 }),
56 pair(preceded(tag_bits(26, 5), take_bits(32)), |i| {
57 Ok((i, IntegerWidth::ThirtyTwo))
58 }),
59 pair(preceded(tag_bits(27, 5), take_bits(64)), |i| {
60 Ok((i, IntegerWidth::SixtyFour))
61 }),
62 ))(input)
63}
64
65fn positive(input: &[u8]) -> IResult<&[u8], DataItem> {
66 bits(preceded(
67 tag_bits(0, 3),
68 map(integer, |(value, bitwidth)| DataItem::Integer {
69 value,
70 bitwidth,
71 }),
72 ))(input)
73}
74
75fn negative(input: &[u8]) -> IResult<&[u8], DataItem> {
76 bits(preceded(
77 tag_bits(1, 3),
78 map(integer, |(value, bitwidth)| DataItem::Negative {
79 value,
80 bitwidth,
81 }),
82 ))(input)
83}
84
85fn definite_bytestring(input: &[u8]) -> IResult<&[u8], ByteString> {
86 let (input, (length, bitwidth)) = bits(preceded(tag_bits(2, 3), integer))(input)?;
87 let length = usize::try_from(length)
88 .map_err(|_| Err::Error(make_error(input, ErrorKind::LengthValue)))?;
89 let (input, data) = take_bytes(length)(input)?;
90 let data = data.to_owned();
91 Ok((input, ByteString { data, bitwidth }))
92}
93
94fn indefinite_bytestring(input: &[u8]) -> IResult<&[u8], DataItem> {
95 preceded(
96 bits(pair(tag_bits(2, 3), tag_bits(31, 5))),
97 map(many_till(definite_bytestring, stop_code), |(strings, _)| {
98 DataItem::IndefiniteByteString(strings)
99 }),
100 )(input)
101}
102
103fn bytestring(input: &[u8]) -> IResult<&[u8], DataItem> {
104 alt((
105 map(definite_bytestring, DataItem::ByteString),
106 indefinite_bytestring,
107 ))(input)
108}
109
110fn definite_textstring(input: &[u8]) -> IResult<&[u8], TextString> {
111 let (input, (length, bitwidth)) = bits(preceded(tag_bits(3, 3), integer))(input)?;
112 let length = usize::try_from(length)
113 .map_err(|_| Err::Error(make_error(input, ErrorKind::LengthValue)))?;
114 let (input, data) = map_res(take_bytes(length), str::from_utf8)(input)?;
115 let data = data.to_owned();
116 Ok((input, TextString { data, bitwidth }))
117}
118
119fn indefinite_textstring(input: &[u8]) -> IResult<&[u8], DataItem> {
120 preceded(
121 bits(pair(tag_bits(3, 3), tag_bits(31, 5))),
122 map(many_till(definite_textstring, stop_code), |(strings, _)| {
123 DataItem::IndefiniteTextString(strings)
124 }),
125 )(input)
126}
127
128fn textstring(input: &[u8]) -> IResult<&[u8], DataItem> {
129 alt((
130 map(definite_textstring, DataItem::TextString),
131 indefinite_textstring,
132 ))(input)
133}
134
135fn definite_array(input: &[u8]) -> IResult<&[u8], DataItem> {
136 let (input, (length, bitwidth)) = bits(preceded(tag_bits(4, 3), integer))(input)?;
137 let (input, data) = count(data_item, length as usize)(input)?;
138 Ok((
139 input,
140 DataItem::Array {
141 data,
142 bitwidth: Some(bitwidth),
143 },
144 ))
145}
146
147fn indefinite_array(input: &[u8]) -> IResult<&[u8], DataItem> {
148 preceded(
149 bits(pair(tag_bits(4, 3), tag_bits(31, 5))),
150 map(many_till(data_item, stop_code), |(data, _)| {
151 DataItem::Array {
152 data,
153 bitwidth: None,
154 }
155 }),
156 )(input)
157}
158
159fn array(input: &[u8]) -> IResult<&[u8], DataItem> {
160 alt((definite_array, indefinite_array))(input)
161}
162
163fn definite_map(input: &[u8]) -> IResult<&[u8], DataItem> {
164 let (input, (length, bitwidth)) = bits(preceded(tag_bits(5, 3), integer))(input)?;
165 let (input, data) = count(pair(data_item, data_item), length as usize)(input)?;
166 Ok((
167 input,
168 DataItem::Map {
169 data,
170 bitwidth: Some(bitwidth),
171 },
172 ))
173}
174
175fn indefinite_map(input: &[u8]) -> IResult<&[u8], DataItem> {
176 preceded(
177 bits(pair(tag_bits(5, 3), tag_bits(31, 5))),
178 map(
179 many_till(pair(data_item, data_item), stop_code),
180 |(data, _)| DataItem::Map {
181 data,
182 bitwidth: None,
183 },
184 ),
185 )(input)
186}
187
188fn data_map(input: &[u8]) -> IResult<&[u8], DataItem> {
189 alt((definite_map, indefinite_map))(input)
190}
191
192fn tag_bitsged(input: &[u8]) -> IResult<&[u8], DataItem> {
193 let (input, (tag, bitwidth)) = bits(preceded(tag_bits(6, 3), integer))(input)?;
194 let (input, value) = data_item(input)?;
195 let value = Box::new(value);
196 Ok((
197 input,
198 DataItem::Tag {
199 tag: Tag(tag),
200 bitwidth,
201 value,
202 },
203 ))
204}
205
206fn float(input: &[u8]) -> IResult<&[u8], DataItem> {
207 bits(preceded(
208 tag_bits(7, 3),
209 map(
210 alt((
211 preceded(
212 tag_bits(25, 5),
213 bytes::<_, _, nom::error::Error<&[u8]>, _, _>(map(be_u16, |u| {
214 (f16::from_bits(u).to_f64(), FloatWidth::Sixteen)
215 })),
216 ),
217 preceded(
218 tag_bits(26, 5),
219 bytes::<_, _, nom::error::Error<&[u8]>, _, _>(map(be_f32, |f| {
220 (f64::from(f), FloatWidth::ThirtyTwo)
221 })),
222 ),
223 preceded(
224 tag_bits(27, 5),
225 bytes::<_, _, nom::error::Error<&[u8]>, _, _>(map(be_f64, |f| {
226 (f, FloatWidth::SixtyFour)
227 })),
228 ),
229 )),
230 |(value, bitwidth)| DataItem::Float { value, bitwidth },
231 ),
232 ))(input)
233}
234
235fn simple(input: &[u8]) -> IResult<&[u8], DataItem> {
236 bits(preceded(
237 tag_bits(7, 3),
238 map(
239 alt((
240 verify(take_bits(5), |&v| v < 24),
241 preceded(tag_bits(24, 5), take_bits(8)),
242 )),
243 |value| DataItem::Simple(Simple(value)),
244 ),
245 ))(input)
246}
247
248fn stop_code(input: &[u8]) -> IResult<&[u8], DataItem> {
249 bits(preceded(
250 tag_bits(7, 3),
251 map(tag_bits(31, 5), |value| DataItem::Simple(Simple(value))),
252 ))(input)
253}
254
255fn data_item(input: &[u8]) -> IResult<&[u8], DataItem> {
256 alt((
257 positive,
258 negative,
259 bytestring,
260 textstring,
261 array,
262 data_map,
263 tag_bitsged,
264 float,
265 simple,
266 ))(input)
267}
268
269pub fn parse_bytes(bytes: impl AsRef<[u8]>) -> Result<DataItem> {
291 let (remaining, parsed) =
292 data_item(bytes.as_ref()).map_err(|e| format!("Parsing error ({e:?})"))?;
293 if !remaining.is_empty() {
294 return Err(format!(
295 "Remaining bytes ({})",
296 data_encoding::HEXLOWER.encode(remaining)
297 )
298 .into());
299 }
300 Ok(parsed)
301}
302
303pub fn parse_bytes_partial(bytes: impl AsRef<[u8]>) -> Result<Option<(DataItem, usize)>> {
341 match data_item(bytes.as_ref()) {
342 Ok((remaining, item)) => Ok(Some((item, bytes.as_ref().len() - remaining.len()))),
343 Err(nom::Err::Incomplete(_)) => Ok(None),
344 Err(nom::Err::Failure(_)) | Err(nom::Err::Error(_)) => Err("Parser error".into()),
345 }
346}