1use crate::traits::*;
2use nom::error::ParseError;
3use nom::{IResult, ToUsize};
4use std::marker::PhantomData;
5
6#[derive(Debug, PartialEq)]
7pub struct LengthData<L, D> {
8 l: PhantomData<L>,
9 pub data: D,
10}
11
12impl<L, D> LengthData<L, D> {
13 pub const fn new(data: D) -> Self {
14 let l = PhantomData;
15 LengthData { l, data }
16 }
17}
18
19impl<L, I, E> Parse<I, E> for LengthData<L, I>
20where
21 I: Clone + PartialEq + InputSlice,
22 E: ParseError<I>,
23 L: Parse<I, E> + ToUsize,
24{
25 fn parse(i: I) -> IResult<I, Self, E> {
26 let (rem, length) = L::parse(i)?;
27 let (rem, data) = rem.take_split(length.to_usize());
28 Ok((rem, LengthData::new(data)))
29 }
30 fn parse_be(i: I) -> IResult<I, Self, E> {
31 let (rem, length) = L::parse_be(i)?;
32 let (rem, data) = rem.take_split(length.to_usize());
33 Ok((rem, LengthData::new(data)))
34 }
35 fn parse_le(i: I) -> IResult<I, Self, E> {
36 let (rem, length) = L::parse_le(i)?;
37 let (rem, data) = rem.take_split(length.to_usize());
38 Ok((rem, LengthData::new(data)))
39 }
40}
41
42pub type LengthDataU8<'a> = LengthData<u8, &'a [u8]>;
43pub type LengthDataU16<'a> = LengthData<u16, &'a [u8]>;
44pub type LengthDataU32<'a> = LengthData<u32, &'a [u8]>;
45pub type LengthDataU64<'a> = LengthData<u64, &'a [u8]>;
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use nom::error::Error;
51
52 #[test]
53 fn test_parse_trait_length_data() {
54 let input: &[u8] = b"\x00\x02ab";
55
56 type T<'a> = LengthData<u16, &'a [u8]>;
57 let res: IResult<_, _, Error<&[u8]>> = <T>::parse(input);
58 assert_eq!(
59 res.unwrap(),
60 (b"" as &[u8], LengthData::new(b"ab" as &[u8]))
61 );
62 }
63
64 #[test]
65 fn test_parse_trait_length_data16() {
66 let input: &[u8] = b"\x00\x02ab";
67
68 type T<'a> = LengthDataU16<'a>;
69 let res: IResult<_, _, Error<&[u8]>> = <T>::parse(input);
70 assert_eq!(
71 res.unwrap(),
72 (b"" as &[u8], LengthData::new(b"ab" as &[u8]))
73 );
74 }
75}