/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-derive-0.10.1/src/traits.rs
Line | Count | Source |
1 | | use nom::bytes::streaming::take; |
2 | | use nom::combinator::{complete, map_res, opt}; |
3 | | use nom::error::{Error, FromExternalError, ParseError}; |
4 | | use nom::multi::{many0, many_m_n}; |
5 | | use nom::number::streaming::*; |
6 | | use nom::sequence::pair; |
7 | | use nom::*; |
8 | | use std::convert::TryFrom; |
9 | | use std::ops::RangeFrom; |
10 | | |
11 | | pub use nom::{InputLength, Slice}; |
12 | | |
13 | | pub trait InputSlice: |
14 | | Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputTake |
15 | | { |
16 | | } |
17 | | impl<'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 | | /// ``` |
95 | | pub trait Parse<I, E = Error<I>> |
96 | | where |
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 | | |
118 | | macro_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 | 16.5M | fn parse_be(i: I) -> IResult<I, Self, E> { |
129 | 16.5M | $be_fn(i) |
130 | 16.5M | } <i8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 96.1k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 96.1k | $be_fn(i) | 130 | 96.1k | } |
<u8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 48.1k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 48.1k | $be_fn(i) | 130 | 48.1k | } |
<u16 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 8.13M | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 8.13M | $be_fn(i) | 130 | 8.13M | } |
<u32 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 149k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 149k | $be_fn(i) | 130 | 149k | } |
<u64 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 191k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 191k | $be_fn(i) | 130 | 191k | } |
<u8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 560k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 560k | $be_fn(i) | 130 | 560k | } |
<u16 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 825k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 825k | $be_fn(i) | 130 | 825k | } |
<i8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 86.5k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 86.5k | $be_fn(i) | 130 | 86.5k | } |
<u8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 43.3k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 43.3k | $be_fn(i) | 130 | 43.3k | } |
<u16 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 3.90M | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 3.90M | $be_fn(i) | 130 | 3.90M | } |
<u32 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 133k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 133k | $be_fn(i) | 130 | 133k | } |
<u64 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 172k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 172k | $be_fn(i) | 130 | 172k | } |
<u8 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 1.61M | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 1.61M | $be_fn(i) | 130 | 1.61M | } |
<u16 as nom_derive::traits::Parse<&[u8]>>::parse_be Line | Count | Source | 128 | 584k | fn parse_be(i: I) -> IResult<I, Self, E> { | 129 | 584k | $be_fn(i) | 130 | 584k | } |
|
131 | 0 | fn parse_le(i: I) -> IResult<I, Self, E> { |
132 | 0 | $le_fn(i) |
133 | 0 | } Unexecuted instantiation: <u8 as nom_derive::traits::Parse<&[u8]>>::parse_le Unexecuted instantiation: <u16 as nom_derive::traits::Parse<&[u8]>>::parse_le Unexecuted instantiation: <u8 as nom_derive::traits::Parse<&[u8]>>::parse_le Unexecuted instantiation: <u16 as nom_derive::traits::Parse<&[u8]>>::parse_le |
134 | | } |
135 | | }; |
136 | | } |
137 | | |
138 | | impl_primitive_type!(i8, be_i8, le_i8); |
139 | | impl_primitive_type!(i16, be_i16, le_i16); |
140 | | impl_primitive_type!(i32, be_i32, le_i32); |
141 | | impl_primitive_type!(i64, be_i64, le_i64); |
142 | | impl_primitive_type!(i128, be_i128, le_i128); |
143 | | |
144 | | impl_primitive_type!(u8, be_u8, le_u8); |
145 | | impl_primitive_type!(u16, be_u16, le_u16); |
146 | | impl_primitive_type!(u32, be_u32, le_u32); |
147 | | impl_primitive_type!(u64, be_u64, le_u64); |
148 | | impl_primitive_type!(u128, be_u128, le_u128); |
149 | | |
150 | | impl_primitive_type!(f32, be_f32, le_f32); |
151 | | impl_primitive_type!(f64, be_f64, le_f64); |
152 | | |
153 | | impl<'a, E> Parse<&'a [u8], E> for String |
154 | | where |
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 | | |
164 | | impl<T, I, E> Parse<I, E> for Option<T> |
165 | | where |
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 | | |
181 | | impl<T, I, E> Parse<I, E> for Vec<T> |
182 | | where |
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 | | |
198 | | impl<T1, T2, I, E> Parse<I, E> for (T1, T2) |
199 | | where |
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)] |
218 | | impl<T, I, E, const N: usize> Parse<I, E> for [T; N] |
219 | | where |
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)] |
240 | | mod 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 | | } |