1 #[cfg(feature = "std")]
2 use crate::internal::IResult;
3 #[cfg(feature = "std")]
4 use std::fmt::Debug;
5
6 #[cfg(feature = "std")]
7 /// Helper trait to show a byte slice as a hex dump
8 pub trait HexDisplay {
9 /// Converts the value of `self` to a hex dump, returning the owned
10 /// string.
to_hex(&self, chunk_size: usize) -> String11 fn to_hex(&self, chunk_size: usize) -> String;
12
13 /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
14 /// string.
to_hex_from(&self, chunk_size: usize, from: usize) -> String15 fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
16 }
17
18 #[cfg(feature = "std")]
19 static CHARS: &'static [u8] = b"0123456789abcdef";
20
21 #[cfg(feature = "std")]
22 impl HexDisplay for [u8] {
23 #[allow(unused_variables)]
to_hex(&self, chunk_size: usize) -> String24 fn to_hex(&self, chunk_size: usize) -> String {
25 self.to_hex_from(chunk_size, 0)
26 }
27
28 #[allow(unused_variables)]
to_hex_from(&self, chunk_size: usize, from: usize) -> String29 fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
30 let mut v = Vec::with_capacity(self.len() * 3);
31 let mut i = from;
32 for chunk in self.chunks(chunk_size) {
33 let s = format!("{:08x}", i);
34 for &ch in s.as_bytes().iter() {
35 v.push(ch);
36 }
37 v.push(b'\t');
38
39 i += chunk_size;
40
41 for &byte in chunk {
42 v.push(CHARS[(byte >> 4) as usize]);
43 v.push(CHARS[(byte & 0xf) as usize]);
44 v.push(b' ');
45 }
46 if chunk_size > chunk.len() {
47 for j in 0..(chunk_size - chunk.len()) {
48 v.push(b' ');
49 v.push(b' ');
50 v.push(b' ');
51 }
52 }
53 v.push(b'\t');
54
55 for &byte in chunk {
56 if (byte >= 32 && byte <= 126) || byte >= 128 {
57 v.push(byte);
58 } else {
59 v.push(b'.');
60 }
61 }
62 v.push(b'\n');
63 }
64
65 String::from_utf8_lossy(&v[..]).into_owned()
66 }
67 }
68
69 #[cfg(feature = "std")]
70 impl HexDisplay for str {
71 #[allow(unused_variables)]
to_hex(&self, chunk_size: usize) -> String72 fn to_hex(&self, chunk_size: usize) -> String {
73 self.to_hex_from(chunk_size, 0)
74 }
75
76 #[allow(unused_variables)]
to_hex_from(&self, chunk_size: usize, from: usize) -> String77 fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
78 self.as_bytes().to_hex_from(chunk_size, from)
79 }
80 }
81
82 #[doc(hidden)]
83 #[macro_export]
84 macro_rules! nom_line (
85 () => (line!());
86 );
87
88 #[doc(hidden)]
89 #[macro_export]
90 macro_rules! nom_println (
91 ($($args:tt)*) => (println!($($args)*));
92 );
93
94 #[doc(hidden)]
95 #[macro_export]
96 macro_rules! nom_stringify (
97 ($($args:tt)*) => (stringify!($($args)*));
98 );
99
100
101 /// Prints a message if the parser fails
102 ///
103 /// The message prints the `Error` or `Incomplete`
104 /// and the parser's calling code
105 ///
106 /// ```
107 /// # #[macro_use] extern crate nom;
108 /// # fn main() {
109 /// named!(f, dbg!( tag!( "abcd" ) ) );
110 ///
111 /// let a = &b"efgh"[..];
112 ///
113 /// // Will print the following message:
114 /// // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
115 /// f(a);
116 /// # }
117 /// ```
118 #[macro_export(local_inner_macros)]
119 macro_rules! dbg (
120 ($i: expr, $submac:ident!( $($args:tt)* )) => (
121 {
122 use $crate::lib::std::result::Result::*;
123 let l = nom_line!();
124 match $submac!($i, $($args)*) {
125 Err(e) => {
126 nom_println!("Err({:?}) at l.{} by ' {} '", e, l, nom_stringify!($submac!($($args)*)));
127 Err(e)
128 },
129 a => a,
130 }
131 }
132 );
133
134 ($i:expr, $f:ident) => (
135 dbg!($i, call!($f));
136 );
137 );
138
139 /// Prints a message and the input if the parser fails
140 ///
141 /// The message prints the `Error` or `Incomplete`
142 /// and the parser's calling code.
143 ///
144 /// It also displays the input in hexdump format
145 ///
146 /// ```rust
147 /// use nom::{IResult, dbg_dmp, bytes::complete::tag};
148 ///
149 /// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
150 /// dbg_dmp(tag("abcd"), "tag")(i)
151 /// }
152 ///
153 /// let a = &b"efghijkl"[..];
154 ///
155 /// // Will print the following message:
156 /// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
157 /// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
158 /// f(a);
159 /// ```
160 #[cfg(feature = "std")]
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>161 pub fn dbg_dmp<'a, F, O, E: Debug>(f: F, context: &'static str) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E>
162 where F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E> {
163 move |i: &'a [u8]| {
164 match f(i) {
165 Err(e) => {
166 println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
167 Err(e)
168 },
169 a => a,
170 }
171 }
172 }
173
174 /// Prints a message and the input if the parser fails
175 ///
176 /// The message prints the `Error` or `Incomplete`
177 /// and the parser's calling code.
178 ///
179 /// It also displays the input in hexdump format
180 ///
181 /// ```ignore
182 /// # #[macro_use] extern crate nom;
183 /// # fn main() {
184 /// named!(f, dbg_dmp!( tag!( "abcd" ) ) );
185 ///
186 /// let a = &b"efghijkl"[..];
187 ///
188 /// // Will print the following message:
189 /// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
190 /// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
191 /// f(a);
192 /// # }
193 #[macro_export(local_inner_macros)]
194 #[cfg(feature = "std")]
195 macro_rules! dbg_dmp (
196 ($i: expr, $submac:ident!( $($args:tt)* )) => (
197 {
198 use $crate::HexDisplay;
199 let l = nom_line!();
200 match $submac!($i, $($args)*) {
201 Err(e) => {
202 nom_println!("Error({:?}) at l.{} by ' {} '\n{}", e, l, nom_stringify!($submac!($($args)*)), $i.to_hex(8));
203 Err(e)
204 },
205 a => a,
206 }
207 }
208 );
209
210 ($i:expr, $f:ident) => (
211 dbg_dmp!($i, call!($f));
212 );
213 );
214
215