Skip to main content

nom_derive/
traits.rs

1use nom::bytes::streaming::take;
2use nom::combinator::{complete, map_res, opt};
3use nom::error::{Error, FromExternalError, ParseError};
4use nom::multi::{many0, many_m_n};
5use nom::number::streaming::*;
6use nom::sequence::pair;
7use nom::*;
8use std::convert::TryFrom;
9use std::ops::RangeFrom;
10
11pub use nom::{InputLength, Slice};
12
13pub trait InputSlice:
14    Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputTake
15{
16}
17impl<'a> InputSlice for &'a [u8] {}
18
19/// Common trait for all parsers in nom-derive
20///
21/// This trait is used to provide parser implementations, usually as generic as possible for the
22/// error type. Implementations are provided for common and primitive types.
23/// The only required method is `parse`, but it is advised to implement the `parse_be` and `parse_le`
24/// methods. Derived code will call one of these methods, depending on the field endianness.
25///
26/// # Example
27///
28/// A possible implementation for the type `u32` is:
29/// ```rust,ignore
30/// impl<I, E> Parse<I, E> for u32
31/// where
32///     E: ParseError<I>,
33///     I: InputSlice,
34/// {
35///     fn parse(i: I) -> IResult<I, Self, E> { be_u32(i) } // default to big-endian
36///     fn parse_be(i: I) -> IResult<I, Self, E> { be_u32(i) }
37///     fn parse_le(i: I) -> IResult<I, Self, E> { le_u32(i) }
38/// }
39/// ```
40///
41/// # Generic type parameters and input
42///
43/// Note: `I` is a generic type that is mostly equivalent to `&'a [u8]`. It is used to
44/// "hide" the lifetime of the input slice `&'a [u8]` and simplify traits implementation
45/// and generation of derived code.
46///
47/// It is possible to implement the `Parse` trait only for `&[u8]` if the
48/// implementation contains non-generic functions.
49///
50/// For example, the implementation for `String` is:
51/// ```rust,ignore
52/// impl<'a, E> Parse<&'a [u8], E> for String
53/// where
54///     E: ParseError<&'a [u8]> + FromExternalError<&'a [u8], std::str::Utf8Error>,
55/// {
56///     fn parse(i: &'a [u8]) -> IResult<&'a [u8], Self, E> {
57///         let (rem, sz) = <u32>::parse(i)?;
58///         let (rem, s) = map_res(take(sz as usize), std::str::from_utf8)(rem)?;
59///         Ok((rem, s.to_owned()))
60///     }
61/// }
62/// ```
63///
64/// # Implementing primitives or specific types
65///
66/// To implement an existing type differently, or a type where implementation was not provided, a
67/// common way is to use a newtype pattern:
68///
69/// ```rust
70/// use nom_derive::{Parse, nom};
71///
72/// use nom::IResult;
73/// use nom::bytes::complete::take;
74/// use nom::combinator::map_res;
75/// use nom::error::{Error, FromExternalError, ParseError};
76///
77/// # #[derive(Debug, PartialEq)]
78/// pub struct MyString(pub String);
79/// impl<'a, E> Parse<&'a [u8], E> for MyString
80/// where
81///     E: ParseError<&'a [u8]> + FromExternalError<&'a [u8], std::str::Utf8Error>,
82/// {
83///     fn parse(i: &'a [u8]) -> IResult<&'a [u8], Self, E> {
84///         let (rem, sz) = <u32>::parse(i)?;
85///         let (rem, s) = map_res(take(sz as usize), std::str::from_utf8)(rem)?;
86///         Ok((rem, MyString(s.to_owned())))
87///     }
88/// }
89///
90/// # let input = b"\x00\x00\x00\x04test";
91/// // error type cannot be inferred by compiler and must be explicit
92/// let res: IResult<_, _, Error<_>> = MyString::parse(input);
93/// # assert_eq!(res, Ok((&input[8..], MyString(String::from("test")))));
94/// ```
95pub trait Parse<I, E = Error<I>>
96where
97    I: InputSlice,
98    E: ParseError<I>,
99    Self: Sized,
100{
101    /// Parse input, not knowing the endianness
102    ///
103    /// Usually, this means choosing between big and little-endian.
104    /// Default implementations for common types are big-endian.
105    fn parse(i: I) -> IResult<I, Self, E>;
106
107    /// Parse input as Big-Endian
108    fn parse_be(i: I) -> IResult<I, Self, E> {
109        Self::parse(i)
110    }
111
112    /// Parse input as Little-Endian
113    fn parse_le(i: I) -> IResult<I, Self, E> {
114        Self::parse(i)
115    }
116}
117
118macro_rules! impl_primitive_type {
119    ( $ty:ty, $be_fn: ident, $le_fn: ident ) => {
120        impl<I, E> Parse<I, E> for $ty
121        where
122            E: ParseError<I>,
123            I: InputSlice,
124        {
125            fn parse(i: I) -> IResult<I, Self, E> {
126                Self::parse_be(i)
127            }
128            fn parse_be(i: I) -> IResult<I, Self, E> {
129                $be_fn(i)
130            }
131            fn parse_le(i: I) -> IResult<I, Self, E> {
132                $le_fn(i)
133            }
134        }
135    };
136}
137
138impl_primitive_type!(i8, be_i8, le_i8);
139impl_primitive_type!(i16, be_i16, le_i16);
140impl_primitive_type!(i32, be_i32, le_i32);
141impl_primitive_type!(i64, be_i64, le_i64);
142impl_primitive_type!(i128, be_i128, le_i128);
143
144impl_primitive_type!(u8, be_u8, le_u8);
145impl_primitive_type!(u16, be_u16, le_u16);
146impl_primitive_type!(u32, be_u32, le_u32);
147impl_primitive_type!(u64, be_u64, le_u64);
148impl_primitive_type!(u128, be_u128, le_u128);
149
150impl_primitive_type!(f32, be_f32, le_f32);
151impl_primitive_type!(f64, be_f64, le_f64);
152
153impl<'a, E> Parse<&'a [u8], E> for String
154where
155    E: ParseError<&'a [u8]> + FromExternalError<&'a [u8], std::str::Utf8Error>,
156{
157    fn parse(i: &'a [u8]) -> IResult<&'a [u8], Self, E> {
158        let (rem, sz) = <u32>::parse(i)?;
159        let (rem, s) = map_res(take(sz as usize), std::str::from_utf8)(rem)?;
160        Ok((rem, s.to_owned()))
161    }
162}
163
164impl<T, I, E> Parse<I, E> for Option<T>
165where
166    I: Clone + InputSlice,
167    E: ParseError<I>,
168    T: Parse<I, E>,
169{
170    fn parse(i: I) -> IResult<I, Self, E> {
171        opt(complete(<T>::parse))(i)
172    }
173    fn parse_be(i: I) -> IResult<I, Self, E> {
174        opt(complete(<T>::parse_be))(i)
175    }
176    fn parse_le(i: I) -> IResult<I, Self, E> {
177        opt(complete(<T>::parse_le))(i)
178    }
179}
180
181impl<T, I, E> Parse<I, E> for Vec<T>
182where
183    I: Clone + PartialEq + InputSlice,
184    E: ParseError<I>,
185    T: Parse<I, E>,
186{
187    fn parse(i: I) -> IResult<I, Self, E> {
188        many0(complete(<T>::parse))(i)
189    }
190    fn parse_be(i: I) -> IResult<I, Self, E> {
191        many0(complete(<T>::parse_be))(i)
192    }
193    fn parse_le(i: I) -> IResult<I, Self, E> {
194        many0(complete(<T>::parse_le))(i)
195    }
196}
197
198impl<T1, T2, I, E> Parse<I, E> for (T1, T2)
199where
200    I: Clone + PartialEq + InputSlice,
201    E: ParseError<I>,
202    T1: Parse<I, E>,
203    T2: Parse<I, E>,
204{
205    fn parse(i: I) -> IResult<I, Self, E> {
206        pair(T1::parse, T2::parse)(i)
207    }
208    fn parse_be(i: I) -> IResult<I, Self, E> {
209        pair(T1::parse_be, T2::parse_be)(i)
210    }
211    fn parse_le(i: I) -> IResult<I, Self, E> {
212        pair(T1::parse_le, T2::parse_le)(i)
213    }
214}
215
216/// *Note: this implementation uses const generics and requires rust >= 1.51*
217#[rustversion::since(1.51)]
218impl<T, I, E, const N: usize> Parse<I, E> for [T; N]
219where
220    I: Clone + PartialEq + InputSlice,
221    E: ParseError<I> + FromExternalError<I, Vec<T>>,
222    T: Parse<I, E>,
223{
224    fn parse(i: I) -> IResult<I, Self, E> {
225        map_res(many_m_n(N, N, complete(<T>::parse)), Self::try_from)(i)
226    }
227    fn parse_be(i: I) -> IResult<I, Self, E> {
228        map_res(many_m_n(N, N, complete(<T>::parse_be)), |v| {
229            Self::try_from(v)
230        })(i)
231    }
232    fn parse_le(i: I) -> IResult<I, Self, E> {
233        map_res(many_m_n(N, N, complete(<T>::parse_le)), |v| {
234            Self::try_from(v)
235        })(i)
236    }
237}
238
239#[cfg(test)]
240mod tests {
241    use super::*;
242
243    #[test]
244    fn test_parse_trait_vec() {
245        let input: &[u8] = b"\x00\x01\x02\x03";
246
247        type T = Vec<u8>;
248        let res: IResult<_, _, Error<&[u8]>> = <T>::parse(input);
249        assert_eq!(res.unwrap(), (b"" as &[u8], vec![0, 1, 2, 3]));
250    }
251
252    #[test]
253    fn test_parse_trait_array() {
254        let input: &[u8] = b"\x00\x01\x02\x03";
255
256        type T = [u8; 4];
257        let res: IResult<_, _, Error<&[u8]>> = <T>::parse(input);
258        assert_eq!(res.unwrap(), (b"" as &[u8], [0, 1, 2, 3]));
259    }
260
261    #[test]
262    fn test_parse_trait_string() {
263        let input: &[u8] = b"\x00\x00\x00\x04abcd";
264
265        type T = String;
266        let res: IResult<_, _, Error<&[u8]>> = <T>::parse_le(input);
267        assert_eq!(res.unwrap(), (b"" as &[u8], String::from("abcd")));
268    }
269}