nom_derive/
helpers.rs

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}