winnow/combinator/debug/
mod.rs

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