-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Robust message parsing #106
Conversation
See also upstream issue: serde-rs/json#647 Though, because cargo guarantees ndjson format, I feel like this lines-based impl is actually more proper. |
27bbd83
to
1a3220f
Compare
See also #102 (comment) for a discussion about this. I personally think it is better to check if the line starts with |
I believe the message is preserved, and that the original serde error can be recovered via downcasting as well: Err(err) => {
eprintln!("err = {:?}", err);
eprintln!("err = {}", err);
let err = err.get_ref().unwrap().downcast_ref::<serde_json::Error>();
eprintln!("err = {:?}", err);
bad += 1
},
-------
running 1 test
err = Custom { kind: InvalidData, error: Error("expected value", line: 1, column: 1) }
err = expected value at line 1 column 1
err = Some(Error("expected value", line: 1, column: 1))
test parse_stream_is_robust ... ok This does sound like a perfect use-case for Checking for Separating messages from other output properly is an interesting, hard problem, which I think doesn't have a perfect solution. Like, you can't even assume utf-8 encoding. So I'd rather keep this API as the ideal solution for dealing with |
More specifically, I can imagine a tad more general interface, which returns an
|
Checking for I don't see how to get the original line from the error object. I'm not sure why it needs to be particularly complex or specialized. It just needs to return a message or a string. I think rustc's bootstrap is a good use case example (code), and shows the code doesn't need to be too complex. BTW, I posted rust-lang/cargo#8069 as a solution to know when to stop parsing the output. Would appreciate if you have any comments on it. |
Ah, sorry, I've completely misunderstood what do you mean by " you lose the actual message", I was thinking about serde's error message.
Hm, what Item type do you envision for the Iterator then? I think it has to be
And in the last case we can't re-use serde_json::Error as is, as it doesn't contain the original string. That gives us something like this: io::Result<Result<Message, (String, Option<serde_json::Error>)>> I don't see nice ways to simplify that substantionaly. It seems like just writing the loop manually as is done in the rustc's bootstrap code might actually be more readable. Writing this all down, I am not actually sure if this streamp-parsing functionality even should exist in this crate, but, if it does, I think it should use the line splitting approach. |
What's the motivation for this? Does cargo ever send us non-JSON output? Shouldn't that be considered a cargo bug and fixed there, instead of awkwardly worked around here? EDIT: NVM, it's linked to #102. I'm asking because I know |
1a3220f#diff-8294540e38a75a7ad333709397296910R480-R481 We hit this in real world with rust-analyzer |
Yea, sorry, I've been meaning to respond. I'll try to come up with a concrete suggestion soon. |
I've been thinking about this for a bit. I think this PR is fine for inclusion as-is. There are two separate problems with
So, no, I don't think this PR is problematic. |
Taking another look at this, what do you think about just adding another variant to |
e60e52c
to
78e9115
Compare
@ehuss I like your solution, implemented it! The drawback is that we now can in theory mask a serde error, but this bug seems unlikely in practice, and, given that we control both producer and consumer of messages here, shouldn't be hard to fix. |
@@ -110,23 +110,51 @@ pub enum Message { | |||
/// This is emitted at the end of the build as the last message. | |||
/// Added in Rust 1.44. | |||
BuildFinished(BuildFinished), | |||
/// A line of text which isn't a cargo or compiler message. | |||
/// Line separator is not included | |||
TextLine(String), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please apply #[serde(skip)]
to this variant, we should never see a text-line
from cargo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, just slapping skip
broke serde: matklad@0b1c8d8
I think it intrracts badly with #[serde(other)]
below. I'll try to read on other
and figure out how to convince serde do what we want to do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that was genuine serde bug: serde-rs/serde#1804
Bumped serde-derive req in Cargo.toml
Published 0.10.0 |
would appreciate a release with this one!