winnow-rs / winnow

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

Owned `ParseError`s #606

Closed 9999years closed 1 week ago

9999years commented 1 month ago

Please complete the following tasks

winnow version

master

Describe your use case

Borrowed ParseErrors are tricky and make it difficult to propagate errors past the parsing code. If there was an owned variant of ParseError, I could easily convert an existing error into (e.g.) a miette::Report or some other owned error type without stringifying it and losing its structured information.

Describe the solution you'd like

Generally, the program which calls the parser will have the input in an owned form somewhere, e.g. from calling std::fs::read_to_string. It's not possible to call parsers with &mut String input directly, because Stream::next_token can't be implemented without reallocating the entire remaining input. Therefore, I would like to be able to replace the input field in the ParseError when an error is encountered:

let input = fs::read_to_string("my-input.txt")?;
let parsed = parser.parse(&mut input.as_str())
    .map_err(|err| err.with_input(input))?; // <- Swap out the `&str` input for `String` here.

Note that this requires the offsets to match up between the old and new inputs; if the offset needs to be adjusted, it would be very useful to have the ParseError constructor available as well.

Alternatives, if applicable

https://github.com/winnow-rs/winnow/discussions/329 suggests implementing ToOwned, but that's not easy for inner references like those ParseError contains.

Additional Context

See: https://github.com/winnow-rs/winnow/discussions/329

epage commented 1 month ago

If there was an owned variant of ParseError, I could easily convert an existing error into (e.g.) a miette::Report or some other owned error type without stringifying it and losing its structured information.

I feel I'm missing something here. Why does making it owned help with working with miette?

We have an example using annotate-snippets. It does use a custom error type though that is also written for the error type to be in a public API which ParseError likely shouldn't be.

https://docs.rs/winnow/latest/winnow/_tutorial/chapter_7/index.html#error-adaptation-and-rendering

epage commented 1 week ago

Without more context, I'm going to go ahead and close this. If there is a reason for us to re-evaluate, let us know!