-
Notifications
You must be signed in to change notification settings - Fork 110
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
types: serialize: constrain the new serialization traits to make them easier and safer to use #855
Conversation
281cabd
to
25677ba
Compare
@Lorak-mmk review ping |
25677ba
to
cc2476c
Compare
v2:
|
e672d2f
to
7038cbc
Compare
v2.1:
|
Introduce the `read_value` function which is able to read a [value], as specified in the CQL protocol. It will be used in the next commit, in order to make the interface of the SerializedValue iterators more correct.
Currently, the SerializedValues' `iter()` method treats both null and unset values as None, and `iter_name_value_pairs()` just assumes that values are never null/unset and panics if they are. Make the interface more correct by adjusting both methods to return RawValue. The iterators will be used in the next commit to implement the fallback that allows to implement `SerializeRow`/`SerializeCql` via legacy `ValueList`/`Value` traits.
7038cbc
to
448acd2
Compare
Actually I have one question: is mod.rs the best place for those new traits and structs? I don't really know Rust conventions in this matter, but it is quite a lot of code, wouldn't it be better to make a new file for it? |
Makes sense, I can move the |
448acd2
to
a00b284
Compare
v3: moved the newly introduced types and traits to a separate module (they are reexported from the place they were defined previously) |
… interfaces Currently, `SerializeRow` and `SerializeCql` traits are just given a mutable reference to a Vec<u8> and asked to append their CQL representation to the end. While simple, there are some issues with the interface: - The serialize method has access to the serialized representation of the values that were appended before it. It's not necessary for a correct implementation to have access to it. - Implementors technically can append any byte sequence to the end, but actually are expected to produce a CQL [value] containing the serialized value. While the `SerializeRow` and `SerializeCql` traits are not generally meant to be manually implemented by the users, we can make the interface easier to use and harder to misuse by making it append-only, restricting what the users are allowed to append and requiring the users to append anything by using a dash of type-level magic. Introduce `RowWriter` and `CellWriter` traits which satisfy the above wishes and constraints, and pass them instead of Vec<u8> in `SerializeRow` and `SerializeCql`. The new traits have two implementations - a Vec<u8> backed one that actually appends the bytes given to it, and a usize-backed one which just measures the length of the output without writing anything. Passing the latter before doing the actual serialization will allow to preallocate the right amount of bytes and then serialize without reallocations. It should be measured whether the reallocation cost always outweighs the calculation cost before implementing this optimization.
a00b284
to
29a37b4
Compare
v3.1: fixed links in the docs |
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 think there is nothing blocking this, do you think we can merge it?
Yes, I'll go ahead and merge it. |
Currently,
SerializeRow
andSerializeCql
traits are just given a mutable reference to a Vec and asked to append their CQL representation to the end. While simple, there are some issues with the interface:While the
SerializeRow
andSerializeCql
traits are not generally meant to be manually implemented by the users, we can make the interface easier to use and harder to misuse by making it append-only, restricting what the users are allowed to append and requiring the users to append anything by using a dash of type-level magic.Introduce
RowWriter
andCellWriter
traits which satisfy the above wishes and constraints, and pass them instead of Vec inSerializeRow
andSerializeCql
.The new traits have two implementations - a Vec backed one that actually appends the bytes given to it, and a usize-backed one which just measures the length of the output without writing anything. Passing the latter before doing the actual serialization will allow to preallocate the right amount of bytes and then serialize without reallocations. It should be measured whether the reallocation cost always outweighs the calculation cost before implementing this optimization.
Refs: #801
I have adjusted the documentation in./docs/source/
.I added appropriateFixes:
annotations to PR description.