WIP: Add byte offset to TextPos. - #140
Conversation
I commented out the test requiring `size_of::<Error> <= 64` because the new data in `TextPos` increases it to 72. That's obviously not the real solution, but I'm not sure what the feasible real solutions are. Left a TODO. I left a TODO about whether to include the byte offset in the `Display` impl for `TextPos`. I added a new `TextPos::start` constructor for the not uncommon case where an error has no meaningful position and so just indicates the start of the data.
Due to the pervasiveness of Personally, I think this should be resolved by more aggressively pessimizing the error case and thereby improve the success case by boxing the error. We do depend on |
|
We should either return a byte offset for error or text position. Not both. |
The problem I see is that this requires access on the original text, i.e. that method would effectively end up on |
|
We can have just a free function, like |
|
Having both values there does not cost us anything, if we box the error. |
|
Having Box is an unnecessary complexity. |
|
It is also a performance optimization as it ensures Admittedly, there is trade-off between added complexity and performance gain, but in my experience, I mostly interact with errors for forwarding and logging when calling into |
|
Oh, you're suggesting to put the whole But I still against storing byte offset in |
|
Thank you both for the feedback. Purely from an API design standpoint, I personally think that errors should only store the byte offset, since that's the more fundamental data, i.e. row/col is a function of the byte position (and data string). Strictly speaking, I don't think that the actual byte -> row/col calculation is really core functionality for this crate, although I still think it makes good sense to include a basic algorithm like this because it's easy and it gives callers an almost trivial way to greatly improve error reports. So I think an ideal API design would be that callers can get the byte offset from the error and then they could optionally pass that to a function to turn it into a row/col. The difficulties would all be in how we get from here to there. It would obviously be a breaking change from the current API. And as discussed, the calculation requires the string, which complicates things a little. The functionality already exists as My ideas for a byte -> row/col API are:
All that said, I'm not opposed to the idea of allowing |
|
I think we should start by replacing As for the API, just a free function should be fine. No need for a Effectively, the new error handling approach should look like: if let Err(error) = roxmltree::Document::parse(src_str) {
let text_pos = roxmltree::text_pos(src_str, error.pos());
eprintln!("Error: {} at {}", error, text_pos); // assuming we have changed `Display` for `roxmltree::Error` as well.
} |
|
Closing this in favor of #141, where I took a stab at @RazrFalcon's preferred approach. |
The goal here is to provide a byte position/offset in errors in addition to a row/col position. The byte position is helpful for callers that want to do more sophisticated error reporting, such as:
The changes are pretty straight forward, and I only ran into one problem that I need feedback to resolve: there's a test that requires
size_of::<Error> <= 64, but the new data inTextPosincreases it to 72. For now I commented that test out just to make sure all the other tests run and pass. Any thoughts about this? Can we just allowErrorto get bigger? Can we remove and/or shrink something else to compensate? Can we potentially do the byte to row/col calculation lazily (e.g. as a method onError) instead of storing row/col data in the error (I'm not sure that the necessary original data string would still be available, plus that could be a pretty break-y change)? Can we hide this behind a feature flag? Or does this error size limit potentially sink this PR/idea?I also left a TODO in the
Displayimpl ofTextPosbecause I'm not sure if/how you might want to incorporate the byte position into that.Sort of unrelatedly -- I added a new
TextPos::startconstructor for the not uncommon case where an error has no meaningful position and so just indicates the start of the data. Seemed like a nice refactor, but it's obviously optional for my goal and I'm happy to change and/or revert that as desired.