winnow-rs / winnow

Making parsing a breeze
https://docs.rs/winnow
Other
525 stars 40 forks source link

Use Display in trace or forward Debug in Located, Stateful and Recoverable #482

Open axelkar opened 7 months ago

axelkar commented 7 months ago

Please complete the following tasks

winnow version

0.6.2

Describe your use case

I want to use winnow/debug but the output looks like this:

> terminated                             | Located {
    initia
 > node Document                         | Located {
    initia
  > separated                            | Located {
    initia
   > alt                                 | Located {
    initia

Also, the separated assert looks like this but it isn't as much of an issue:

assert ``separated` separator parser must always consume` failed at Recoverable {
    input: Located {
        initial: Stateful {
            input: "",
            state: "src",
        },
        input: Stateful {
            input: "",
            state: "src",
        },
    },
    errors: [],
    is_recoverable: true,
}

Describe the solution you'd like

https://github.com/winnow-rs/winnow/blob/df311c1d20ea8680b9852e73658fd400ac76513f/src/combinator/debug/internals.rs#L149

-    let mut debug_slice = format!("{:#?}", input.raw());
+    let mut debug_slice = format!("{}", input.raw());

OR do the following for Located, Stateful and Recoverable

https://github.com/winnow-rs/winnow/blob/df311c1d20ea8680b9852e73658fd400ac76513f/src/stream/mod.rs#L109

-#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
+impl<I: crate::lib::std::fmt::Debug> crate::lib::std::fmt::Debug for Located<I> {
+    fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
+        self.input.fmt(f)
+    }
+}

Alternatives, if applicable

Make a new trait to display in trace to avoid breaking Debug for other use cases.

Additional Context

-

epage commented 7 months ago

Not all streams implement Display, like &[u8]. We offer BStr but I don't want to limit this feature to someone switching off of &[u8].

Alternatively, we could change the alternate form (#) of debug to be a pass through for these wrapper types

baoyachi commented 5 months ago

Perhaps we could define a custom Format trait within winnow, enabling formatting for any arbitrary type.

epage commented 5 months ago

Since most people don't implement a custom stream, a new trait is likely fine. The main question about how we should handle custom tokens. Right now, you can its pretty minimal to support those (see custom token docs) and this gets into slices vs tokes. Maybe we could just use debug alternate on tokens.

This would be a breaking change still. For now, I've gone forward with the workaround I mentioned

aDotInTheVoid commented 4 months ago

Since most people don't implement a custom stream, a new trait is likely fine.

I wonder if you could instead have .raw() (or equivalent after renaming) take a f: &mut Formatter, and have it be responsible for writing out the tokens.

This would look something like

trait Stream: core::fmt::Debug {
   ...

  fn fmt_remaining(&self, f: &mut core::fmt::Formatter<'_>) {
    core::fmt::Debug::fmt(self, f)
  }
}

This way, adaptor streams like Stateful, Located and Partial can use there forwarding logic for the debug view, while also not hiding information form format!("{:#?}") (in non-winnow code).

It also means that we can remove the use of {:#?} in the debug view, providing a good output for when stream is &[Token] (cc #516).