• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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