blob: c74cb4e04017b2de0b755ced6aff6f5c6fede232 [file] [log] [blame]
Yiming Jingebb18722021-07-16 13:15:12 -07001//! Helper macros
2
3use nom::bytes::complete::take;
4use nom::combinator::map_res;
5use nom::combinator::rest;
6pub use nom::error::{make_error, ErrorKind, ParseError};
7use nom::HexDisplay;
8pub use nom::{IResult, Needed};
9
10#[doc(hidden)]
11pub mod export {
12 pub use core::{fmt, mem, ptr};
13}
14
15/// Helper macro for newtypes: declare associated constants and implement Display trait
16#[macro_export]
17macro_rules! newtype_enum (
18 (@collect_impl, $name:ident, $($key:ident = $val:expr),* $(,)*) => {
19 $( pub const $key : $name = $name($val); )*
20 };
21
22 (@collect_disp, $name:ident, $f:ident, $m:expr, $($key:ident = $val:expr),* $(,)*) => {
23 match $m {
24 $( $val => write!($f, stringify!{$key}), )*
25 n => write!($f, "{}({} / 0x{:x})", stringify!{$name}, n, n)
26 }
27 };
28
29 // entry
30 (impl $name:ident {$($body:tt)*}) => (
31 #[allow(non_upper_case_globals)]
32 impl $name {
33 newtype_enum!{@collect_impl, $name, $($body)*}
34 }
35 );
36
37 // entry with display
38 (impl display $name:ident {$($body:tt)*}) => (
39 newtype_enum!(impl $name { $($body)* });
40
41 impl $crate::export::fmt::Display for $name {
42 fn fmt(&self, f: &mut $crate::export::fmt::Formatter) -> $crate::export::fmt::Result {
43 newtype_enum!(@collect_disp, $name, f, self.0, $($body)*)
44 }
45 }
46 );
47
48 // entry with display and debug
49 (impl debug $name:ident {$($body:tt)*}) => (
50 newtype_enum!(impl display $name { $($body)* });
51
52 impl $crate::export::fmt::Debug for $name {
53 fn fmt(&self, f: &mut $crate::export::fmt::Formatter) -> $crate::export::fmt::Result {
54 write!(f, "{}", self)
55 }
56 }
57 );
58);
59
60/// Helper macro for nom parsers: raise error if the condition is true
61///
62/// This macro is used when using custom errors
63#[macro_export]
64macro_rules! custom_check (
65 ($i:expr, $cond:expr, $err:expr) => (
66 {
67 if $cond {
68 Err(::nom::Err::Error($err))
69 } else {
70 Ok(($i, ()))
71 }
72 }
73 );
74);
75
76/// Helper macro for nom parsers: raise error if the condition is true
77///
78/// This macro is used when using `ErrorKind`
79#[macro_export]
80macro_rules! error_if (
81 ($i:expr, $cond:expr, $err:expr) => (
82 {
83 use nom::error_position;
84 if $cond {
85 Err(::nom::Err::Error(error_position!($i, $err)))
86 } else {
87 Ok(($i, ()))
88 }
89 }
90 );
91);
92
93/// Helper macro for nom parsers: raise error if input is not empty
94///
95/// Deprecated - use `nom::eof`
96#[macro_export]
97#[deprecated(since = "2.0.0")]
98macro_rules! empty (
99 ($i:expr,) => (
100 {
101 use nom::eof;
102 eof!($i,)
103 }
104 );
105);
106
107/// Helper macro for nom parsers: run first parser if condition is true, else second parser
108#[macro_export]
109macro_rules! cond_else (
110 ($i:expr, $cond:expr, $expr_then:ident!($($args_then:tt)*), $expr_else:ident!($($args_else:tt)*)) => (
111 {
112 if $cond { $expr_then!($i, $($args_then)*) }
113 else { $expr_else!($i, $($args_else)*) }
114 }
115 );
116 ($i:expr, $cond:expr, $expr_then:expr, $expr_else:ident!($($args_else:tt)*)) => (
117 cond_else!($i, $cond, call!($expr_then), $expr_else!($($args_else)*))
118 );
119 ($i:expr, $cond:expr, $expr_then:ident!($($args_then:tt)*), $expr_else:expr) => (
120 cond_else!($i, $cond, $expr_then!($($args_then)*), call!($expr_else))
121 );
122 ($i:expr, $cond:expr, $expr_then:expr, $expr_else:expr) => (
123 cond_else!($i, $cond, call!($expr_then), call!($expr_else))
124 );
125);
126
127/// Dump the remaining bytes to stderr, formatted as hex
128pub fn dbg_dmp_rest(i: &[u8]) -> IResult<&[u8], ()> {
129 map!(i, peek!(call!(rest)), |r| eprintln!("\n{}\n", r.to_hex(16)))
130}
131
132#[deprecated(since = "3.0.1", note = "please use `be_var_u64` instead")]
133/// Read an entire slice as a big-endian value.
134///
135/// Returns the value as `u64`. This function checks for integer overflows, and returns a
136/// `Result::Err` value if the value is too big.
137pub fn bytes_to_u64(s: &[u8]) -> Result<u64, &'static str> {
138 let mut u: u64 = 0;
139
140 if s.is_empty() {
141 return Err("empty");
142 };
143 if s.len() > 8 {
144 return Err("overflow");
145 }
146 for &c in s {
147 let u1 = u << 8;
148 u = u1 | (c as u64);
149 }
150
151 Ok(u)
152}
153
154/// Read a slice as a big-endian value.
155#[macro_export]
156macro_rules! parse_hex_to_u64 (
157 ( $i:expr, $size:expr ) => {
158 map_res(take($size as usize), $crate::combinator::be_var_u64)($i)
159 };
160);
161
162/// Read 3 bytes as an unsigned integer
163#[deprecated(since = "0.5.0", note = "please use `be_u24` instead")]
164#[allow(deprecated)]
165#[inline]
166pub fn parse_uint24(i: &[u8]) -> IResult<&[u8], u64> {
167 map_res(take(3usize), bytes_to_u64)(i)
168}
169
170//named!(parse_hex4<&[u8], u64>, parse_hex_to_u64!(4));
171
172/// Parse a slice and return a fixed-sized array of bytes
173///
174/// This creates a copy of input data
175/// Uses unsafe code
176#[macro_export]
177macro_rules! slice_fixed(
178 ( $i:expr, $count:expr ) => (
179 {
180 let cnt = $count;
181 let ires: IResult<_,_> = if $i.len() < cnt {
182 Err(::nom::Err::Incomplete(Needed::new(cnt)))
183 } else {
184 let mut res: [u8; $count] = unsafe {
185 $crate::export::mem::MaybeUninit::uninit().assume_init()
186 };
187 unsafe{$crate::export::ptr::copy($i.as_ptr(), res.as_mut_ptr(), cnt)};
188 Ok((&$i[cnt..],res))
189 };
190 ires
191 }
192 );
193);
194
195/// Combination and flat_map! and take! as first combinator
196#[macro_export]
197macro_rules! flat_take (
198 ($i:expr, $len:expr, $f:ident) => ({
199 if $i.len() < $len { Err(::nom::Err::Incomplete(::nom::Needed::new($len))) }
200 else {
201 let taken = &$i[0..$len];
202 let rem = &$i[$len..];
203 match $f(taken) {
204 Ok((_,res)) => Ok((rem,res)),
205 Err(e) => Err(e)
206 }
207 }
208 });
209 ($i:expr, $len:expr, $submac:ident!( $($args:tt)*)) => ({
210 if $i.len() < $len { Err(::nom::Err::Incomplete(::nom::Needed::new($len))) }
211 else {
212 let taken = &$i[0..$len];
213 let rem = &$i[$len..];
214 match $submac!(taken, $($args)*) {
215 Ok((_,res)) => Ok((rem,res)),
216 Err(e) => Err(e)
217 }
218 }
219 });
220);
221
222/// Apply combinator, trying to "upgrade" error to next error type (using the `Into` or `From`
223/// traits).
224#[macro_export]
225macro_rules! upgrade_error (
226 ($i:expr, $submac:ident!( $($args:tt)*) ) => ({
227 upgrade_error!( $submac!( $i, $($args)* ) )
228 });
229 ($i:expr, $f:expr) => ({
230 upgrade_error!( call!($i, $f) )
231 });
232 ($e:expr) => ({
233 match $e {
234 Ok(o) => Ok(o),
235 Err(::nom::Err::Error(e)) => Err(::nom::Err::Error(e.into())),
236 Err(::nom::Err::Failure(e)) => Err(::nom::Err::Failure(e.into())),
237 Err(::nom::Err::Incomplete(i)) => Err(::nom::Err::Incomplete(i)),
238 }
239 });
240);
241
242/// Apply combinator, trying to "upgrade" error to next error type (using the `Into` or `From`
243/// traits).
244#[macro_export]
245macro_rules! upgrade_error_to (
246 ($i:expr, $ty:ty, $submac:ident!( $($args:tt)*) ) => ({
247 upgrade_error_to!( $ty, $submac!( $i, $($args)* ) )
248 });
249 ($i:expr, $ty:ty, $f:expr) => ({
250 upgrade_error_to!( $ty, call!($i, $f) )
251 });
252 ($ty:ty, $e:expr) => ({
253 match $e {
254 Ok(o) => Ok(o),
255 Err(::nom::Err::Error(e)) => Err(::nom::Err::Error(e.into::<$ty>())),
256 Err(::nom::Err::Failure(e)) => Err(::nom::Err::Failure(e.into::<$ty>())),
257 Err(::nom::Err::Incomplete(i)) => Err(::nom::Err::Incomplete(i)),
258 }
259 });
260);
261
262/// Nom combinator that returns the given expression unchanged
263#[macro_export]
264macro_rules! q {
265 ($i:expr, $x:expr) => {{
266 Ok(($i, $x))
267 }};
268}
269
270/// Align input value to the next multiple of n bytes
271/// Valid only if n is a power of 2
272#[macro_export]
273macro_rules! align_n2 {
274 ($x:expr, $n:expr) => {
275 ($x + ($n - 1)) & !($n - 1)
276 };
277}
278
279/// Align input value to the next multiple of 4 bytes
280#[macro_export]
281macro_rules! align32 {
282 ($x:expr) => {
283 $crate::align_n2!($x, 4)
284 };
285}
286
287#[cfg(test)]
288mod tests {
289 use nom::error::ErrorKind;
290 use nom::number::streaming::{be_u16, be_u32, be_u8};
291 use nom::{Err, IResult, Needed};
292
293 #[test]
294 #[allow(unsafe_code)]
295 fn test_slice_fixed() {
296 let empty = &b""[..];
297 let b = &[0x01, 0x02, 0x03, 0x04, 0x05];
298
299 let res = slice_fixed!(b, 4);
300 assert_eq!(res, Ok((&b[4..], [1, 2, 3, 4])));
301
302 // can we still use the result ?
303 match res {
304 Ok((rem, _)) => {
305 let res2: IResult<&[u8], u8> = be_u8(rem);
306 assert_eq!(res2, Ok((empty, 5)));
307 }
308 _ => (),
309 }
310 }
311
312 #[test]
313 #[allow(unsafe_code)]
314 fn test_slice_fixed_incomplete() {
315 let b = &[0x01, 0x02, 0x03, 0x04, 0x05];
316 let res = slice_fixed!(b, 8);
317 assert_eq!(res, Err(Err::Incomplete(Needed::new(8))));
318 }
319
320 #[test]
321 fn test_error_if() {
322 let empty = &b""[..];
323 let res: IResult<&[u8], ()> = error_if!(empty, true, ErrorKind::Tag);
324 assert_eq!(res, Err(Err::Error(error_position!(empty, ErrorKind::Tag))));
325 }
326
327 #[test]
328 fn test_cond_else() {
329 let input = &[0x01][..];
330 let empty = &b""[..];
331 let a = 1;
332 fn parse_u8(i: &[u8]) -> IResult<&[u8], u8> {
333 be_u8(i)
334 }
335 assert_eq!(
336 cond_else!(input, a == 1, call!(parse_u8), value!(0x02)),
337 Ok((empty, 0x01))
338 );
339 assert_eq!(
340 cond_else!(input, a == 1, parse_u8, value!(0x02)),
341 Ok((empty, 0x01))
342 );
343 assert_eq!(
344 cond_else!(input, a == 2, parse_u8, value!(0x02)),
345 Ok((input, 0x02))
346 );
347 assert_eq!(
348 cond_else!(input, a == 1, value!(0x02), parse_u8),
349 Ok((input, 0x02))
350 );
351 let res: IResult<&[u8], u8> = cond_else!(input, a == 1, parse_u8, parse_u8);
352 assert_eq!(res, Ok((empty, 0x01)));
353 }
354
355 #[test]
356 fn test_newtype_enum() {
357 #[derive(Debug, PartialEq, Eq)]
358 struct MyType(pub u8);
359
360 newtype_enum! {
361 impl display MyType {
362 Val1 = 0,
363 Val2 = 1
364 }
365 }
366
367 assert_eq!(MyType(0), MyType::Val1);
368 assert_eq!(MyType(1), MyType::Val2);
369
370 assert_eq!(format!("{}", MyType(0)), "Val1");
371 assert_eq!(format!("{}", MyType(4)), "MyType(4 / 0x4)");
372 }
373 #[test]
374 fn test_flat_take() {
375 let input = &[0x00, 0x01, 0xff];
376 // read first 2 bytes and use correct combinator: OK
377 let res: IResult<&[u8], u16> = flat_take!(input, 2, be_u16);
378 assert_eq!(res, Ok((&input[2..], 0x0001)));
379 // read 3 bytes and use 2: OK (some input is just lost)
380 let res: IResult<&[u8], u16> = flat_take!(input, 3, be_u16);
381 assert_eq!(res, Ok((&b""[..], 0x0001)));
382 // read 2 bytes and a combinator requiring more bytes
383 let res: IResult<&[u8], u32> = flat_take!(input, 2, be_u32);
384 assert_eq!(res, Err(Err::Incomplete(Needed::new(2))));
385 // test with macro as sub-combinator
386 let res: IResult<&[u8], u16> = flat_take!(input, 2, be_u16);
387 assert_eq!(res, Ok((&input[2..], 0x0001)));
388 }
389
390 #[test]
391 fn test_q() {
392 let empty = &b""[..];
393 let res: IResult<&[u8], &str, ErrorKind> = q!(empty, "test");
394 assert_eq!(res, Ok((empty, "test")));
395 }
396
397 #[test]
398 fn test_align32() {
399 assert_eq!(align32!(3), 4);
400 assert_eq!(align32!(4), 4);
401 assert_eq!(align32!(5), 8);
402 assert_eq!(align32!(5u32), 8);
403 assert_eq!(align32!(5i32), 8);
404 assert_eq!(align32!(5usize), 8);
405 }
406}