| #[cfg(feature = "std")] |
| use crate::internal::IResult; |
| #[cfg(feature = "std")] |
| use std::fmt::Debug; |
| |
| #[cfg(feature = "std")] |
| /// Helper trait to show a byte slice as a hex dump |
| pub trait HexDisplay { |
| /// Converts the value of `self` to a hex dump, returning the owned |
| /// string. |
| fn to_hex(&self, chunk_size: usize) -> String; |
| |
| /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned |
| /// string. |
| fn to_hex_from(&self, chunk_size: usize, from: usize) -> String; |
| } |
| |
| #[cfg(feature = "std")] |
| static CHARS: &'static [u8] = b"0123456789abcdef"; |
| |
| #[cfg(feature = "std")] |
| impl HexDisplay for [u8] { |
| #[allow(unused_variables)] |
| fn to_hex(&self, chunk_size: usize) -> String { |
| self.to_hex_from(chunk_size, 0) |
| } |
| |
| #[allow(unused_variables)] |
| fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { |
| let mut v = Vec::with_capacity(self.len() * 3); |
| let mut i = from; |
| for chunk in self.chunks(chunk_size) { |
| let s = format!("{:08x}", i); |
| for &ch in s.as_bytes().iter() { |
| v.push(ch); |
| } |
| v.push(b'\t'); |
| |
| i += chunk_size; |
| |
| for &byte in chunk { |
| v.push(CHARS[(byte >> 4) as usize]); |
| v.push(CHARS[(byte & 0xf) as usize]); |
| v.push(b' '); |
| } |
| if chunk_size > chunk.len() { |
| for j in 0..(chunk_size - chunk.len()) { |
| v.push(b' '); |
| v.push(b' '); |
| v.push(b' '); |
| } |
| } |
| v.push(b'\t'); |
| |
| for &byte in chunk { |
| if (byte >= 32 && byte <= 126) || byte >= 128 { |
| v.push(byte); |
| } else { |
| v.push(b'.'); |
| } |
| } |
| v.push(b'\n'); |
| } |
| |
| String::from_utf8_lossy(&v[..]).into_owned() |
| } |
| } |
| |
| #[cfg(feature = "std")] |
| impl HexDisplay for str { |
| #[allow(unused_variables)] |
| fn to_hex(&self, chunk_size: usize) -> String { |
| self.to_hex_from(chunk_size, 0) |
| } |
| |
| #[allow(unused_variables)] |
| fn to_hex_from(&self, chunk_size: usize, from: usize) -> String { |
| self.as_bytes().to_hex_from(chunk_size, from) |
| } |
| } |
| |
| #[doc(hidden)] |
| #[macro_export] |
| macro_rules! nom_line ( |
| () => (line!()); |
| ); |
| |
| #[doc(hidden)] |
| #[macro_export] |
| macro_rules! nom_println ( |
| ($($args:tt)*) => (println!($($args)*)); |
| ); |
| |
| #[doc(hidden)] |
| #[macro_export] |
| macro_rules! nom_stringify ( |
| ($($args:tt)*) => (stringify!($($args)*)); |
| ); |
| |
| |
| /// Prints a message if the parser fails |
| /// |
| /// The message prints the `Error` or `Incomplete` |
| /// and the parser's calling code |
| /// |
| /// ``` |
| /// # #[macro_use] extern crate nom; |
| /// # fn main() { |
| /// named!(f, dbg!( tag!( "abcd" ) ) ); |
| /// |
| /// let a = &b"efgh"[..]; |
| /// |
| /// // Will print the following message: |
| /// // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) ' |
| /// f(a); |
| /// # } |
| /// ``` |
| #[macro_export(local_inner_macros)] |
| macro_rules! dbg ( |
| ($i: expr, $submac:ident!( $($args:tt)* )) => ( |
| { |
| use $crate::lib::std::result::Result::*; |
| let l = nom_line!(); |
| match $submac!($i, $($args)*) { |
| Err(e) => { |
| nom_println!("Err({:?}) at l.{} by ' {} '", e, l, nom_stringify!($submac!($($args)*))); |
| Err(e) |
| }, |
| a => a, |
| } |
| } |
| ); |
| |
| ($i:expr, $f:ident) => ( |
| dbg!($i, call!($f)); |
| ); |
| ); |
| |
| /// Prints a message and the input if the parser fails |
| /// |
| /// The message prints the `Error` or `Incomplete` |
| /// and the parser's calling code. |
| /// |
| /// It also displays the input in hexdump format |
| /// |
| /// ```rust |
| /// use nom::{IResult, dbg_dmp, bytes::complete::tag}; |
| /// |
| /// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> { |
| /// dbg_dmp(tag("abcd"), "tag")(i) |
| /// } |
| /// |
| /// let a = &b"efghijkl"[..]; |
| /// |
| /// // Will print the following message: |
| /// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) ' |
| /// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl |
| /// f(a); |
| /// ``` |
| #[cfg(feature = "std")] |
| pub fn dbg_dmp<'a, F, O, E: Debug>(f: F, context: &'static str) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E> |
| where F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E> { |
| move |i: &'a [u8]| { |
| match f(i) { |
| Err(e) => { |
| println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8)); |
| Err(e) |
| }, |
| a => a, |
| } |
| } |
| } |
| |
| /// Prints a message and the input if the parser fails |
| /// |
| /// The message prints the `Error` or `Incomplete` |
| /// and the parser's calling code. |
| /// |
| /// It also displays the input in hexdump format |
| /// |
| /// ```ignore |
| /// # #[macro_use] extern crate nom; |
| /// # fn main() { |
| /// named!(f, dbg_dmp!( tag!( "abcd" ) ) ); |
| /// |
| /// let a = &b"efghijkl"[..]; |
| /// |
| /// // Will print the following message: |
| /// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) ' |
| /// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl |
| /// f(a); |
| /// # } |
| #[macro_export(local_inner_macros)] |
| #[cfg(feature = "std")] |
| macro_rules! dbg_dmp ( |
| ($i: expr, $submac:ident!( $($args:tt)* )) => ( |
| { |
| use $crate::HexDisplay; |
| let l = nom_line!(); |
| match $submac!($i, $($args)*) { |
| Err(e) => { |
| nom_println!("Error({:?}) at l.{} by ' {} '\n{}", e, l, nom_stringify!($submac!($($args)*)), $i.to_hex(8)); |
| Err(e) |
| }, |
| a => a, |
| } |
| } |
| ); |
| |
| ($i:expr, $f:ident) => ( |
| dbg_dmp!($i, call!($f)); |
| ); |
| ); |
| |