blob: 488bbfb7d18f5b42e1d780a3bae68d341403597b [file] [log] [blame]
#[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));
);
);