Skip to content
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

Deserialization refactor: add new deserialization traits #961

Closed
5 tasks done
Tracked by #462
wprzytula opened this issue Mar 19, 2024 · 0 comments · Fixed by #970
Closed
5 tasks done
Tracked by #462

Deserialization refactor: add new deserialization traits #961

wprzytula opened this issue Mar 19, 2024 · 0 comments · Fixed by #970
Assignees
Milestone

Comments

@wprzytula
Copy link
Collaborator

wprzytula commented Mar 19, 2024

Sub-task of #462.

The new API

The new API is based on two new traits, DeserializeCql and DeserializeRow:

pub trait DeserializeCql<'frame>
where
    Self: Sized,
{
    /// Checks whether this type can be deserialized from given CQL type.
    fn type_check(typ: &ColumnType) -> Result<(), ParseError>;

    /// Deserialize from given bytes.
    /// The function may assume that `type_check` was called and it succeeded.
    fn deserialize(
        typ: &'frame ColumnType,
        v: Option<FrameSlice<'frame>>,
    ) -> Result<Self, ParseError>;
}
pub trait DeserializeRow<'frame>
where
    Self: Sized,
{
    /// Checks whether this type can be deserialized from given row.
    fn type_check(specs: &[ColumnSpec]) -> Result<(), ParseError>;

    /// Deserialize from given bytes.
    /// The function may assume that `type_check` was called and it succeeded.
    fn deserialize(row: ColumnIterator<'frame>) -> Result<Self, ParseError>;
}

Instead of receiving pre-parsed data, both traits receive objects that borrow data from the serialized frame - hence the 'frame lifetime parameter. This allows the types being deserialized to allocate only when they need to (e.g. in case of String). However, the new API also allows types that borrow data from the serialized frame - for example &[u8] or &str. There is also a third option - the type being deserialized can also share ownership of the serialized frame - for example, you can deserialize blob to a bytes::Bytes, which will keep the original, serialized frame alive while it is alive. This is easier to use than slices or strs, but one needs to be careful as even a tiny blob will keep the memory for the whole serialized frame alive, which can lead to space leaks.

Another notable changes is the type_check method. In case of DeserializeRow it receives more comprehensive information than FromRow, which include column names, and now maching column names to fields is possible. The derive for DeserializeRow has that functionality. Moreover, because type checking is separate from deserialize, it can be done only once when a response is received - if the page with response has 1000 rows then we only need to call type_check once per page but deserialize once per row. deserialize can assume that type_check has been called and it can avoid some potentially expensive type checks.

Tasks

  1. wprzytula
  2. area/deserialization
    wprzytula
  3. area/deserialization cpp-rust-driver-p0
    wprzytula
  4. area/deserialization cpp-rust-driver-p0
    wprzytula
  5. area/deserialization area/documentation
    wprzytula
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant