• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![cfg_attr(feature = "debug", allow(clippy::std_instead_of_core))]
2 
3 #[cfg(feature = "debug")]
4 mod internals;
5 
6 use crate::error::ErrMode;
7 use crate::stream::Stream;
8 use crate::Parser;
9 
10 /// Trace the execution of the parser
11 ///
12 /// Note that [`Parser::context`] also provides high level trace information.
13 ///
14 /// See [tutorial][crate::_tutorial::chapter_8] for more details.
15 ///
16 /// # Example
17 ///
18 /// ```rust
19 /// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
20 /// # use winnow::token::take_while;
21 /// # use winnow::stream::AsChar;
22 /// # use winnow::prelude::*;
23 /// use winnow::combinator::trace;
24 ///
25 /// fn short_alpha<'s>(s: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> {
26 ///   trace("short_alpha",
27 ///     take_while(3..=6, AsChar::is_alpha)
28 ///   ).parse_next(s)
29 /// }
30 ///
31 /// assert_eq!(short_alpha.parse_peek(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
32 /// assert_eq!(short_alpha.parse_peek(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
33 /// assert_eq!(short_alpha.parse_peek(b"latin"), Ok((&b""[..], &b"latin"[..])));
34 /// assert_eq!(short_alpha.parse_peek(b"ed"), Err(ErrMode::Backtrack(InputError::new(&b"ed"[..], ErrorKind::Slice))));
35 /// assert_eq!(short_alpha.parse_peek(b"12345"), Err(ErrMode::Backtrack(InputError::new(&b"12345"[..], ErrorKind::Slice))));
36 /// ```
37 #[cfg_attr(not(feature = "debug"), allow(unused_variables))]
38 #[cfg_attr(not(feature = "debug"), allow(unused_mut))]
39 #[cfg_attr(not(feature = "debug"), inline(always))]
trace<I: Stream, O, E>( name: impl crate::lib::std::fmt::Display, parser: impl Parser<I, O, E>, ) -> impl Parser<I, O, E>40 pub fn trace<I: Stream, O, E>(
41     name: impl crate::lib::std::fmt::Display,
42     parser: impl Parser<I, O, E>,
43 ) -> impl Parser<I, O, E> {
44     #[cfg(feature = "debug")]
45     {
46         internals::Trace::new(parser, name)
47     }
48     #[cfg(not(feature = "debug"))]
49     {
50         parser
51     }
52 }
53 
54 #[cfg_attr(not(feature = "debug"), allow(unused_variables))]
trace_result<T, E>( name: impl crate::lib::std::fmt::Display, res: &Result<T, ErrMode<E>>, )55 pub(crate) fn trace_result<T, E>(
56     name: impl crate::lib::std::fmt::Display,
57     res: &Result<T, ErrMode<E>>,
58 ) {
59     #[cfg(feature = "debug")]
60     {
61         let depth = internals::Depth::existing();
62         let severity = internals::Severity::with_result(res);
63         internals::result(*depth, &name, severity);
64     }
65 }
66 
67 pub(crate) struct DisplayDebug<D>(pub(crate) D);
68 
69 impl<D: crate::lib::std::fmt::Debug> crate::lib::std::fmt::Display for DisplayDebug<D> {
fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result70     fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
71         write!(f, "{:?}", self.0)
72     }
73 }
74 
75 #[test]
76 #[cfg(feature = "std")]
77 #[cfg_attr(miri, ignore)]
78 #[cfg(unix)]
79 #[cfg(feature = "debug")]
example()80 fn example() {
81     use term_transcript::{test::TestConfig, ShellOptions};
82 
83     let path = snapbox::cmd::compile_example("string", ["--features=debug"]).unwrap();
84 
85     let current_dir = path.parent().unwrap();
86     let cmd = path.file_name().unwrap();
87     // HACK: term_transcript doesn't allow non-UTF8 paths
88     let cmd = format!("./{}", cmd.to_string_lossy());
89 
90     TestConfig::new(
91         ShellOptions::default()
92             .with_current_dir(current_dir)
93             .with_env("CLICOLOR_FORCE", "1"),
94     )
95     .test("assets/trace.svg", [cmd.as_str()]);
96 }
97