Yiming Jing | ebb1872 | 2021-07-16 13:15:12 -0700 | [diff] [blame] | 1 | //! Helper macros |
| 2 | |
| 3 | use nom::bytes::complete::take; |
| 4 | use nom::combinator::map_res; |
| 5 | use nom::combinator::rest; |
| 6 | pub use nom::error::{make_error, ErrorKind, ParseError}; |
| 7 | use nom::HexDisplay; |
| 8 | pub use nom::{IResult, Needed}; |
| 9 | |
| 10 | #[doc(hidden)] |
| 11 | pub 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] |
| 17 | macro_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] |
| 64 | macro_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] |
| 80 | macro_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")] |
| 98 | macro_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] |
| 109 | macro_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 |
| 128 | pub 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. |
| 137 | pub 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] |
| 156 | macro_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] |
| 166 | pub 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] |
| 177 | macro_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] |
| 197 | macro_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] |
| 225 | macro_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] |
| 245 | macro_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] |
| 264 | macro_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] |
| 273 | macro_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] |
| 281 | macro_rules! align32 { |
| 282 | ($x:expr) => { |
| 283 | $crate::align_n2!($x, 4) |
| 284 | }; |
| 285 | } |
| 286 | |
| 287 | #[cfg(test)] |
| 288 | mod 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 | } |