-
Notifications
You must be signed in to change notification settings - Fork 744
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
Serialize to binary if the serde format is not human readable #1044
Conversation
FYI: The is not fully fleshed out in method names and documentation, will fix that before merging. |
This implements the KISS suggested in serde-rs#790. It is possible that one of the other approaches may be better but this seemed like the simplest one to reignite som discussion. Personally I find the original suggestion of adding two traits perhaps slightly cleaner in theory but I think it ends up more complicated in the end since the added traits also need to be duplicated to to the `Seed` traits. Closes serde-rs#790
cff024d
to
0dccbb1
Compare
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.
I am still on board with this approach. Thanks for getting things moving!
Could you brainstorm a few advantages and disadvantages of using &self vs no &self?
With The erased-serde crate will need to take Downside is that one needs an instance to check if the format is human readable. Seems to me that would always be the case? Maybe in the future with const functions it would be useful to query
|
Makes sense to me. The erased-serde case is a great point, I had not thought of how that would work. What would you recommend for rolling this out? If I release this now, it would be a breaking change to use this in any of our currently built-in Serialize impls later because you might have serialized one in human-readable form to a non-self-describing format and then be unable to deserialize it in non-human-readable form. That seems to mean we need to update all built-in impls like IpAddr in the same release as this change, right? Changing a format from human-readable to non-human-readable must be done in a breaking change right? |
Wouldn't it make the most sense for formats to simply allow deserialisation from all formats (readable and not) and only serialise to one or the other depending on whether it's marked as readable or not? That makes the most sense to me. |
That is not possible for formats such as bincode which require that the deserialized value tell the deserializer what the upcoming data is as the serialized data is just bytes without knowledge what values it contains. |
Yeah :/ . In theory we could document that making a format aware of the human readable distinction require a breaking change. The formats could then avoid the breaking change by making |
Makes sense. We still need to update all the relevant Serialize and Deserialize impls in this PR. |
Since we know exactly how many bytes we should serialize as we can hint to the serializer that it is not required which further reduces the serialized size when compared to just serializing as bytes.
I believe only ip addresses and socket address needs a non-human readble serialization? Those are the only types which use Just need to document a bit better and this should be done. EDIT: Also need to fix serialization of net::IpAddr as they I broke roundtripping in ad3335e as well as tests for that. |
2ba61b3
to
945d12c
Compare
This is ready for review now! |
@dtolnay Any problems with the current implementation? |
Sorry I didn't get a chance to review this weekend, but it is high on my list and I will try to get to it in the next couple days. Can you think of any other backward-compatible ways to expose this in serde_test without adding so many new functions? |
I could change it to use the builder pattern, but that won't make it smaller now but would only serve to reduce the API surface if more configuration parameters were added in the future. |
I suppose I could move the |
How about either of these?
Not saying these are backward compatibly or better, but a possible direction to think about. |
That would work and would be backwards compatible modulo deref coercions failing due to being a generic parameter. Seems more difficult to understand though.
How would that work? A wrapper around a generic |
struct Unreadable<T>(T);
impl<T> Serialize for Unreadable<T>
where T: Serialize
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
self.0.serialize(UnreadableSerializer(serializer))
}
}
struct UnreadableSerializer<S>(S);
impl<S> Serializer for UnreadableSerializer<S>
where S: Serializer
{
fn is_human_readable(&self) -> bool {
false
}
/* forward others */
} |
Ah, yep that would work. Doing the same thing for Personally I feel like it is not very intuitive. If I were to come in with no prior knowledge and look at serde_test I'd find the solution rather strange :/ |
I agree that we may be able to come up with something more intuitive. I will keep brainstorming alternatives. For completeness, here is what that approach would have looked like in tests: let s = /* ... */;
// In human readable formats, field `timestamp` serializes as ISO 8601.
assert_tokens(&Readable(s), &[
Token::Struct { name: "S", len: 1 },
Token::Str("timestamp"),
Token::String("2017-09-26T21:49:25Z"),
Token::StructEnd,
]);
// In binary formats, field `timestamp` serializes in compact byte form.
assert_tokens(&Unreadable(s), &[
Token::Struct { name: "S", len: 1 },
Token::Str("timestamp"),
Token::Bytes(&[226, 152, 131]),
Token::StructEnd,
]); |
Builder pattern on Serializer::new(tokens)
.readable(false)
.assert_serialize(&serialize_value)
Deserializer::new(tokens)
.readable(false)
.assert_deserialize() |
I am still not sold on the serde_test piece of this but I don't want that to block the feature any longer. Let's get this released in serde and then take a bit more time to design the test api. To that end:
|
@dtolnay Sounds reasonable, should get to it in a few days. |
This is sort of bikeshedding but Btw, this is a great improvement 😄 |
It should be enough to just hide the functions though as |
Until a good API can be found
73c372d
to
e9b530a
Compare
... by utilizing that bincode is not human readable. Uses the changes in serde-rs/serde#1044 which allows data formats to report that they are not human readable. This lets certain types serialize themselves into a more compact form as they know that the serialized form does not need to be readable. BREAKING CHANGE This changes how types serialize themselves if they detect the `is_human_readable` state.
... by utilizing that bincode is not human readable. Uses the changes in serde-rs/serde#1044 which allows data formats to report that they are not human readable. This lets certain types serialize themselves into a more compact form as they know that the serialized form does not need to be readable. Closes bincode-org#215 BREAKING CHANGE This changes how types serialize themselves if they detect the `is_human_readable` state.
... by utilizing that bincode is not human readable. Uses the changes in serde-rs/serde#1044 which allows data formats to report that they are not human readable. This lets certain types serialize themselves into a more compact form as they know that the serialized form does not need to be readable. Closes bincode-org#215 BREAKING CHANGE This changes how types serialize themselves if they detect the `is_human_readable` state.
... by utilizing that bincode is not human readable. Uses the changes in serde-rs/serde#1044 which allows data formats to report that they are not human readable. This lets certain types serialize themselves into a more compact form as they know that the serialized form does not need to be readable. Closes #215 BREAKING CHANGE This changes how types serialize themselves if they detect the `is_human_readable` state.
This implements the KISS suggested in #790.
It is possible that one of the other approaches may be better but this
seemed like the simplest one to reignite som discussion.
Personally I find the original suggestion of adding two traits perhaps slightly
cleaner in theory but I think it ends up more complicated in the end
since the added traits also need to be duplicated to to the
Seed
traits.
Example usage in https://github.com/rust-lang-nursery/uuid: Marwes/uuid@f908fd3
Closes #790