Skip to content

Commit f6441d5

Browse files
committed
parametrize DeserializeValue with two lifetimes
`DeserializeValue` requires two types of data in order to perform deserialization: 1) a reference to the CQL frame (a FrameSlice), 2) the type of the column being deserialized, being part of the ResultMetadata. It's important to understand what is a _deserialized value_. It's not just an implementor of DeserializeValue; there are some implementors of `DeserializeValue` who are not yet final values, but **partially** deserialized types that support further deserialization - _value deserializers_, such as `ListlikeIterator` or `UdtIterator`. _Value deserializers_, as they still need to deserialize some value, are naturally bound by 'metadata lifetime. However, _values_ are completely deserialized, so they should not be bound by 'metadata - only by 'frame. When deserializing owned values, both the frame and the metadata can have any lifetime and it's not important. When deserializing borrowing values, however, they borrow from the frame, so their lifetime must necessarily be bound by the lifetime of the frame. Metadata is only needed for the deserialization, so its lifetime does not abstractly bound the deserialized value. Up to this commit, DeserializeValue was only parametrized by one lifetime: 'frame, which bounded both the frame slice and the metadata. (why? see next paragraph about value deserializers) This was done that way due to an assumption that both the metadata and the frame (shared using Bytes) will be owned by the same entity. However, the new idea of deserializing result metadata to a borrowed form (to save allocations) makes result metadata's lifetime shorter than the frame's lifetime. Not to unnecessarily shorten the deserialized values' lifetime, a separate lifetime parameter is introduced for result metadata: 'metadata. Up to this commit, value deserializers could only be parametrized by 'frame lifetime. Therefore, borrowed metadata held by value deserializers limits the 'frame lifetime to its lifetime. Hence, values deserialized by value deserializers must have been bounded by the lifetime of the metadata. The commit is large, but the changes are mostly mechanical, by adding the second lifetime parameter. DeserializeRow & friends are going to get the second lifetime parameter, too, but for now they pass 'frame as both lifetime parameters of DeserializeValue.
1 parent 20583fc commit f6441d5

File tree

8 files changed

+228
-192
lines changed

8 files changed

+228
-192
lines changed

scylla-cql/src/frame/response/result.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,7 +1013,7 @@ pub fn deser_cql_value(
10131013
CqlValue::List(l)
10141014
}
10151015
Map(_key_type, _value_type) => {
1016-
let iter = MapIterator::<'_, CqlValue, CqlValue>::deserialize(typ, v)?;
1016+
let iter = MapIterator::<'_, '_, CqlValue, CqlValue>::deserialize(typ, v)?;
10171017
let m: Vec<(CqlValue, CqlValue)> = iter.collect::<StdResult<_, _>>()?;
10181018
CqlValue::Map(m)
10191019
}

scylla-cql/src/types/deserialize/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! Deserialization is based on two traits:
44
//!
5-
//! - A type that implements `DeserializeValue<'frame>` can be deserialized
5+
//! - A type that implements `DeserializeValue<'frame, 'metadata>` can be deserialized
66
//! from a single _CQL value_ - i.e. an element of a row in the query result,
77
//! - A type that implements `DeserializeRow<'frame>` can be deserialized
88
//! from a single _row_ of a query result.
@@ -57,7 +57,7 @@
5757
//! #[error("Expected non-null")]
5858
//! ExpectedNonNull,
5959
//! }
60-
//! impl<'frame> DeserializeValue<'frame> for MyVec {
60+
//! impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MyVec {
6161
//! fn type_check(typ: &ColumnType) -> Result<(), TypeCheckError> {
6262
//! if let ColumnType::Blob = typ {
6363
//! return Ok(());
@@ -66,7 +66,7 @@
6666
//! }
6767
//!
6868
//! fn deserialize(
69-
//! _typ: &'frame ColumnType,
69+
//! _typ: &'metadata ColumnType<'metadata>,
7070
//! v: Option<FrameSlice<'frame>>,
7171
//! ) -> Result<Self, DeserializationError> {
7272
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))
@@ -98,7 +98,7 @@
9898
//! #[error("Expected non-null")]
9999
//! ExpectedNonNull,
100100
//! }
101-
//! impl<'a, 'frame> DeserializeValue<'frame> for MySlice<'a>
101+
//! impl<'a, 'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MySlice<'a>
102102
//! where
103103
//! 'frame: 'a,
104104
//! {
@@ -110,7 +110,7 @@
110110
//! }
111111
//!
112112
//! fn deserialize(
113-
//! _typ: &'frame ColumnType,
113+
//! _typ: &'metadata ColumnType<'metadata>,
114114
//! v: Option<FrameSlice<'frame>>,
115115
//! ) -> Result<Self, DeserializationError> {
116116
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))
@@ -150,7 +150,7 @@
150150
//! #[error("Expected non-null")]
151151
//! ExpectedNonNull,
152152
//! }
153-
//! impl<'frame> DeserializeValue<'frame> for MyBytes {
153+
//! impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MyBytes {
154154
//! fn type_check(typ: &ColumnType) -> Result<(), TypeCheckError> {
155155
//! if let ColumnType::Blob = typ {
156156
//! return Ok(());
@@ -159,7 +159,7 @@
159159
//! }
160160
//!
161161
//! fn deserialize(
162-
//! _typ: &'frame ColumnType,
162+
//! _typ: &'metadata ColumnType<'metadata>,
163163
//! v: Option<FrameSlice<'frame>>,
164164
//! ) -> Result<Self, DeserializationError> {
165165
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))

scylla-cql/src/types/deserialize/row.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,15 @@ macro_rules! impl_tuple {
183183
($($Ti:ident),*; $($idx:literal),*; $($idf:ident),*) => {
184184
impl<'frame, $($Ti),*> DeserializeRow<'frame> for ($($Ti,)*)
185185
where
186-
$($Ti: DeserializeValue<'frame>),*
186+
$($Ti: DeserializeValue<'frame, 'frame>),*
187187
{
188188
fn type_check(specs: &[ColumnSpec]) -> Result<(), TypeCheckError> {
189189
const TUPLE_LEN: usize = (&[$($idx),*] as &[i32]).len();
190190

191191
let column_types_iter = || specs.iter().map(|spec| spec.typ().clone().into_owned());
192192
if let [$($idf),*] = &specs {
193193
$(
194-
<$Ti as DeserializeValue<'frame>>::type_check($idf.typ())
194+
<$Ti as DeserializeValue<'frame, 'frame>>::type_check($idf.typ())
195195
.map_err(|err| mk_typck_err::<Self>(column_types_iter(), BuiltinTypeCheckErrorKind::ColumnTypeCheckFailed {
196196
column_index: $idx,
197197
column_name: specs[$idx].name().to_owned(),
@@ -217,7 +217,7 @@ macro_rules! impl_tuple {
217217
$idx
218218
)).map_err(deser_error_replace_rust_name::<Self>)?;
219219

220-
<$Ti as DeserializeValue<'frame>>::deserialize(column.spec.typ(), column.slice)
220+
<$Ti as DeserializeValue<'frame, 'frame>>::deserialize(column.spec.typ(), column.slice)
221221
.map_err(|err| mk_deser_err::<Self>(BuiltinDeserializationErrorKind::ColumnDeserializationFailed {
222222
column_index: column.index,
223223
column_name: column.spec.name().to_owned(),

0 commit comments

Comments
 (0)