-
Notifications
You must be signed in to change notification settings - Fork 207
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
consensus::State deserialization fixes #680
Conversation
That's interesting. These failures didn't show up in local testing. Checking... |
All right, the test problem is my fault, I didn't run the full test suite after changing the |
Codecov Report
@@ Coverage Diff @@
## master #680 +/- ##
========================================
+ Coverage 39.2% 39.4% +0.2%
========================================
Files 190 191 +1
Lines 12552 12595 +43
Branches 3237 3241 +4
========================================
+ Hits 4927 4974 +47
+ Misses 7381 7373 -8
- Partials 244 248 +4
Continue to review full report at Codecov.
|
use std::convert::TryFrom; | ||
use std::fmt::Formatter; | ||
|
||
struct PartSetHeaderTotalStringOrU32; |
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.
Do we really need to define a type + a visitor?
I wonder if this can be expressed instead with just the serialize
and deserialize
functions, and invoked via a #[serde(with = "crate::serializers::part_set_header_total")]
attribute?
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.
Instead of a visitor, we would use the deserialize
method provided by the Deserialize
trait: https://docs.rs/serde/1.0.117/serde/trait.Deserialize.html
eg. to deserialize a u64
:
u64::deserialize(deserializer)
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.
Yes, that was the original solution. Unfortunately, the deserializer in the above example is not clonable and I need to be able to derive if the incoming input is an integer or a string.
Here's the outline of the original solution:
let try_string = String::deserialize(deserializer.clone());
if try_string.is_err() {
u32::deserialize(deserializer)?
} else {
try_string.unwrap()
}
The deserialize function consumes the deserializer.
So, you need to be able to figure out if the incoming data is an integer or a String before trying to deserialize it. Short of writing our own deserializer, the Visitor seemed the right solution. The "either string or struct" example in the Serde documentation also uses this solution: https://serde.rs/string-or-struct.html
Edit: obviously, I could have removed the if condition and used .or()
or similar, this is a quick draft.
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.
Right, makes sense! That's an unfortunate limitation/design decision of serde
that I wasn't aware of. Thanks for pointing me to the serde doc, had completely forgotten about this example, my bad.
All good then :)
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.
No worries, I'm grateful that you point out possible optimizations!
Fixes #679.
This should make the
consensus::State
struct backwards compatible for JSON deserialization. Note that serialization will always use the new format which is not backwards compatible because of a rename fromparts
topart_set_header
in one field.