Skip to content

Commit 6d14015

Browse files
authored
Merge pull request #1101 from wprzytula/new-deserialization-with-two-lifetimes
Parametrize `Deserialize{Value,Row}` with two lifetimes: `'frame` and `'metadata` separately
2 parents 7e73e25 + 2394d10 commit 6d14015

File tree

10 files changed

+453
-248
lines changed

10 files changed

+453
-248
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: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,56 @@
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,
7-
//! - A type that implements `DeserializeRow<'frame>` can be deserialized
7+
//! - A type that implements `DeserializeRow<'frame, 'metadata>` can be deserialized
88
//! from a single _row_ of a query result.
99
//!
1010
//! Those traits are quite similar to each other, both in the idea behind them
1111
//! and the interface that they expose.
1212
//!
13+
//! It's important to understand what is a _deserialized type_. It's not just
14+
//! an implementor of Deserialize{Value, Row}; there are some implementors of
15+
//! `Deserialize{Value, Row}` who are not yet final types, but **partially**
16+
//! deserialized types that support further deserialization - _type
17+
//! deserializers_, such as `ListlikeIterator`, `UdtIterator` or `ColumnIterator`.
18+
//!
19+
//! # Lifetime parameters
20+
//!
21+
//! - `'frame` is the lifetime of the frame. Any deserialized type that is going to borrow
22+
//! from the frame must have its lifetime bound by `'frame`.
23+
//! - `'metadata` is the lifetime of the result metadata. As result metadata is only needed
24+
//! for the very deserialization process and the **final** deserialized types (i.e. those
25+
//! that are not going to deserialize anything else, opposite of e.g. `MapIterator`) can
26+
//! later live independently of the metadata, this is different from `'frame`.
27+
//!
28+
//! _Type deserializers_, as they still need to deserialize some type, are naturally bound
29+
//! by 'metadata lifetime. However, final types are completely deserialized, so they should
30+
//! not be bound by 'metadata - only by 'frame.
31+
//!
32+
//! Rationale:
33+
//! `DeserializeValue` requires two types of data in order to perform
34+
//! deserialization:
35+
//! 1) a reference to the CQL frame (a FrameSlice),
36+
//! 2) the type of the column being deserialized, being part of the
37+
//! ResultMetadata.
38+
//!
39+
//! Similarly, `DeserializeRow` requires two types of data in order to
40+
//! perform deserialization:
41+
//! 1) a reference to the CQL frame (a FrameSlice),
42+
//! 2) a slice of specifications of all columns in the row, being part of
43+
//! the ResultMetadata.
44+
//!
45+
//! When deserializing owned types, both the frame and the metadata can have
46+
//! any lifetime and it's not important. When deserializing borrowed types,
47+
//! however, they borrow from the frame, so their lifetime must necessarily
48+
//! be bound by the lifetime of the frame. Metadata is only needed for the
49+
//! deserialization, so its lifetime does not abstractly bound the
50+
//! deserialized value. Not to unnecessarily shorten the deserialized
51+
//! values' lifetime to the metadata's lifetime (due to unification of
52+
//! metadata's and frame's lifetime in value deserializers), a separate
53+
//! lifetime parameter is introduced for result metadata: `'metadata`.
54+
//!
1355
//! # `type_check` and `deserialize`
1456
//!
1557
//! The deserialization process is divided into two parts: type checking and
@@ -57,7 +99,7 @@
5799
//! #[error("Expected non-null")]
58100
//! ExpectedNonNull,
59101
//! }
60-
//! impl<'frame> DeserializeValue<'frame> for MyVec {
102+
//! impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MyVec {
61103
//! fn type_check(typ: &ColumnType) -> Result<(), TypeCheckError> {
62104
//! if let ColumnType::Blob = typ {
63105
//! return Ok(());
@@ -66,7 +108,7 @@
66108
//! }
67109
//!
68110
//! fn deserialize(
69-
//! _typ: &'frame ColumnType,
111+
//! _typ: &'metadata ColumnType<'metadata>,
70112
//! v: Option<FrameSlice<'frame>>,
71113
//! ) -> Result<Self, DeserializationError> {
72114
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))
@@ -98,7 +140,7 @@
98140
//! #[error("Expected non-null")]
99141
//! ExpectedNonNull,
100142
//! }
101-
//! impl<'a, 'frame> DeserializeValue<'frame> for MySlice<'a>
143+
//! impl<'a, 'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MySlice<'a>
102144
//! where
103145
//! 'frame: 'a,
104146
//! {
@@ -110,7 +152,7 @@
110152
//! }
111153
//!
112154
//! fn deserialize(
113-
//! _typ: &'frame ColumnType,
155+
//! _typ: &'metadata ColumnType<'metadata>,
114156
//! v: Option<FrameSlice<'frame>>,
115157
//! ) -> Result<Self, DeserializationError> {
116158
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))
@@ -150,7 +192,7 @@
150192
//! #[error("Expected non-null")]
151193
//! ExpectedNonNull,
152194
//! }
153-
//! impl<'frame> DeserializeValue<'frame> for MyBytes {
195+
//! impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MyBytes {
154196
//! fn type_check(typ: &ColumnType) -> Result<(), TypeCheckError> {
155197
//! if let ColumnType::Blob = typ {
156198
//! return Ok(());
@@ -159,7 +201,7 @@
159201
//! }
160202
//!
161203
//! fn deserialize(
162-
//! _typ: &'frame ColumnType,
204+
//! _typ: &'metadata ColumnType<'metadata>,
163205
//! v: Option<FrameSlice<'frame>>,
164206
//! ) -> Result<Self, DeserializationError> {
165207
//! v.ok_or_else(|| DeserializationError::new(MyDeserError::ExpectedNonNull))

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

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@ use std::marker::PhantomData;
66

77
/// Iterates over the whole result, returning rows.
88
#[derive(Debug)]
9-
pub struct RowIterator<'frame> {
10-
specs: &'frame [ColumnSpec<'frame>],
9+
pub struct RowIterator<'frame, 'metadata> {
10+
specs: &'metadata [ColumnSpec<'metadata>],
1111
remaining: usize,
1212
slice: FrameSlice<'frame>,
1313
}
1414

15-
impl<'frame> RowIterator<'frame> {
15+
impl<'frame, 'metadata> RowIterator<'frame, 'metadata> {
1616
/// Creates a new iterator over rows from a serialized response.
1717
///
1818
/// - `remaining` - number of the remaining rows in the serialized response,
1919
/// - `specs` - information about columns of the serialized response,
2020
/// - `slice` - a [FrameSlice] that points to the serialized rows data.
2121
#[inline]
22-
pub fn new(remaining: usize, specs: &'frame [ColumnSpec], slice: FrameSlice<'frame>) -> Self {
22+
pub fn new(
23+
remaining: usize,
24+
specs: &'metadata [ColumnSpec<'metadata>],
25+
slice: FrameSlice<'frame>,
26+
) -> Self {
2327
Self {
2428
specs,
2529
remaining,
@@ -29,7 +33,7 @@ impl<'frame> RowIterator<'frame> {
2933

3034
/// Returns information about the columns of rows that are iterated over.
3135
#[inline]
32-
pub fn specs(&self) -> &'frame [ColumnSpec] {
36+
pub fn specs(&self) -> &'metadata [ColumnSpec<'metadata>] {
3337
self.specs
3438
}
3539

@@ -41,8 +45,8 @@ impl<'frame> RowIterator<'frame> {
4145
}
4246
}
4347

44-
impl<'frame> Iterator for RowIterator<'frame> {
45-
type Item = Result<ColumnIterator<'frame>, DeserializationError>;
48+
impl<'frame, 'metadata> Iterator for RowIterator<'frame, 'metadata> {
49+
type Item = Result<ColumnIterator<'frame, 'metadata>, DeserializationError>;
4650

4751
#[inline]
4852
fn next(&mut self) -> Option<Self::Item> {
@@ -78,20 +82,20 @@ impl<'frame> Iterator for RowIterator<'frame> {
7882
/// A typed version of [RowIterator] which deserializes the rows before
7983
/// returning them.
8084
#[derive(Debug)]
81-
pub struct TypedRowIterator<'frame, R> {
82-
inner: RowIterator<'frame>,
85+
pub struct TypedRowIterator<'frame, 'metadata, R> {
86+
inner: RowIterator<'frame, 'metadata>,
8387
_phantom: PhantomData<R>,
8488
}
8589

86-
impl<'frame, R> TypedRowIterator<'frame, R>
90+
impl<'frame, 'metadata, R> TypedRowIterator<'frame, 'metadata, R>
8791
where
88-
R: DeserializeRow<'frame>,
92+
R: DeserializeRow<'frame, 'metadata>,
8993
{
9094
/// Creates a new [TypedRowIterator] from given [RowIterator].
9195
///
9296
/// Calls `R::type_check` and fails if the type check fails.
9397
#[inline]
94-
pub fn new(raw: RowIterator<'frame>) -> Result<Self, TypeCheckError> {
98+
pub fn new(raw: RowIterator<'frame, 'metadata>) -> Result<Self, TypeCheckError> {
9599
R::type_check(raw.specs())?;
96100
Ok(Self {
97101
inner: raw,
@@ -101,7 +105,7 @@ where
101105

102106
/// Returns information about the columns of rows that are iterated over.
103107
#[inline]
104-
pub fn specs(&self) -> &'frame [ColumnSpec] {
108+
pub fn specs(&self) -> &'metadata [ColumnSpec<'metadata>] {
105109
self.inner.specs()
106110
}
107111

@@ -113,9 +117,9 @@ where
113117
}
114118
}
115119

116-
impl<'frame, R> Iterator for TypedRowIterator<'frame, R>
120+
impl<'frame, 'metadata, R> Iterator for TypedRowIterator<'frame, 'metadata, R>
117121
where
118-
R: DeserializeRow<'frame>,
122+
R: DeserializeRow<'frame, 'metadata>,
119123
{
120124
type Item = Result<R, DeserializationError>;
121125

@@ -179,7 +183,7 @@ mod tests {
179183
let raw_data = serialize_cells([Some(CELL1), Some(CELL2), Some(CELL2), Some(CELL1)]);
180184
let specs = [spec("b1", ColumnType::Blob), spec("b2", ColumnType::Blob)];
181185
let iter = RowIterator::new(2, &specs, FrameSlice::new(&raw_data));
182-
let mut iter = TypedRowIterator::<'_, (&[u8], Vec<u8>)>::new(iter).unwrap();
186+
let mut iter = TypedRowIterator::<'_, '_, (&[u8], Vec<u8>)>::new(iter).unwrap();
183187

184188
let (c11, c12) = iter.next().unwrap().unwrap();
185189
assert_eq!(c11, CELL1);
@@ -197,6 +201,6 @@ mod tests {
197201
let raw_data = Bytes::new();
198202
let specs = [spec("b1", ColumnType::Blob), spec("b2", ColumnType::Blob)];
199203
let iter = RowIterator::new(0, &specs, FrameSlice::new(&raw_data));
200-
assert!(TypedRowIterator::<'_, (i32, i64)>::new(iter).is_err());
204+
assert!(TypedRowIterator::<'_, '_, (i32, i64)>::new(iter).is_err());
201205
}
202206
}

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,29 @@ use crate::frame::response::result::{ColumnSpec, ColumnType, CqlValue, Row};
1010

1111
/// Represents a raw, unparsed column value.
1212
#[non_exhaustive]
13-
pub struct RawColumn<'frame> {
13+
pub struct RawColumn<'frame, 'metadata> {
1414
pub index: usize,
15-
pub spec: &'frame ColumnSpec<'frame>,
15+
pub spec: &'metadata ColumnSpec<'metadata>,
1616
pub slice: Option<FrameSlice<'frame>>,
1717
}
1818

1919
/// Iterates over columns of a single row.
2020
#[derive(Clone, Debug)]
21-
pub struct ColumnIterator<'frame> {
22-
specs: std::iter::Enumerate<std::slice::Iter<'frame, ColumnSpec<'frame>>>,
21+
pub struct ColumnIterator<'frame, 'metadata> {
22+
specs: std::iter::Enumerate<std::slice::Iter<'metadata, ColumnSpec<'metadata>>>,
2323
slice: FrameSlice<'frame>,
2424
}
2525

26-
impl<'frame> ColumnIterator<'frame> {
26+
impl<'frame, 'metadata> ColumnIterator<'frame, 'metadata> {
2727
/// Creates a new iterator over a single row.
2828
///
2929
/// - `specs` - information about columns of the serialized response,
3030
/// - `slice` - a [FrameSlice] which points to the serialized row.
3131
#[inline]
32-
pub(crate) fn new(specs: &'frame [ColumnSpec], slice: FrameSlice<'frame>) -> Self {
32+
pub(crate) fn new(
33+
specs: &'metadata [ColumnSpec<'metadata>],
34+
slice: FrameSlice<'frame>,
35+
) -> Self {
3336
Self {
3437
specs: specs.iter().enumerate(),
3538
slice,
@@ -44,8 +47,8 @@ impl<'frame> ColumnIterator<'frame> {
4447
}
4548
}
4649

47-
impl<'frame> Iterator for ColumnIterator<'frame> {
48-
type Item = Result<RawColumn<'frame>, DeserializationError>;
50+
impl<'frame, 'metadata> Iterator for ColumnIterator<'frame, 'metadata> {
51+
type Item = Result<RawColumn<'frame, 'metadata>, DeserializationError>;
4952

5053
#[inline]
5154
fn next(&mut self) -> Option<Self::Item> {
@@ -84,7 +87,7 @@ impl<'frame> Iterator for ColumnIterator<'frame> {
8487
/// The crate also provides a derive macro which allows to automatically
8588
/// implement the trait for a custom type. For more details on what the macro
8689
/// is capable of, see its documentation.
87-
pub trait DeserializeRow<'frame>
90+
pub trait DeserializeRow<'frame, 'metadata>
8891
where
8992
Self: Sized,
9093
{
@@ -100,7 +103,7 @@ where
100103
/// the row's type. Note that `deserialize` is not an unsafe function,
101104
/// so it should not use the assumption about `type_check` being called
102105
/// as an excuse to run `unsafe` code.
103-
fn deserialize(row: ColumnIterator<'frame>) -> Result<Self, DeserializationError>;
106+
fn deserialize(row: ColumnIterator<'frame, 'metadata>) -> Result<Self, DeserializationError>;
104107
}
105108

106109
// raw deserialization as ColumnIterator
@@ -111,14 +114,14 @@ where
111114
// Implementing DeserializeRow for it allows us to simplify our interface. For example,
112115
// we have `QueryResult::rows<T: DeserializeRow>()` - you can put T = ColumnIterator
113116
// instead of having a separate rows_raw function or something like this.
114-
impl<'frame> DeserializeRow<'frame> for ColumnIterator<'frame> {
117+
impl<'frame, 'metadata> DeserializeRow<'frame, 'metadata> for ColumnIterator<'frame, 'metadata> {
115118
#[inline]
116119
fn type_check(_specs: &[ColumnSpec]) -> Result<(), TypeCheckError> {
117120
Ok(())
118121
}
119122

120123
#[inline]
121-
fn deserialize(row: ColumnIterator<'frame>) -> Result<Self, DeserializationError> {
124+
fn deserialize(row: ColumnIterator<'frame, 'metadata>) -> Result<Self, DeserializationError> {
122125
Ok(row)
123126
}
124127
}
@@ -140,15 +143,17 @@ make_error_replace_rust_name!(
140143
/// While no longer encouraged (because the new framework encourages deserializing
141144
/// directly into desired types, entirely bypassing [CqlValue]), this can be indispensable
142145
/// for some use cases, i.e. those involving dynamic parsing (ORMs?).
143-
impl<'frame> DeserializeRow<'frame> for Row {
146+
impl<'frame, 'metadata> DeserializeRow<'frame, 'metadata> for Row {
144147
#[inline]
145148
fn type_check(_specs: &[ColumnSpec]) -> Result<(), TypeCheckError> {
146149
// CqlValues accept all types, no type checking needed.
147150
Ok(())
148151
}
149152

150153
#[inline]
151-
fn deserialize(mut row: ColumnIterator<'frame>) -> Result<Self, DeserializationError> {
154+
fn deserialize(
155+
mut row: ColumnIterator<'frame, 'metadata>,
156+
) -> Result<Self, DeserializationError> {
152157
let mut columns = Vec::with_capacity(row.size_hint().0);
153158
while let Some(column) = row
154159
.next()
@@ -181,17 +186,17 @@ impl<'frame> DeserializeRow<'frame> for Row {
181186
/// and needed conversions, issuing meaningful errors in case something goes wrong.
182187
macro_rules! impl_tuple {
183188
($($Ti:ident),*; $($idx:literal),*; $($idf:ident),*) => {
184-
impl<'frame, $($Ti),*> DeserializeRow<'frame> for ($($Ti,)*)
189+
impl<'frame, 'metadata, $($Ti),*> DeserializeRow<'frame, 'metadata> for ($($Ti,)*)
185190
where
186-
$($Ti: DeserializeValue<'frame>),*
191+
$($Ti: DeserializeValue<'frame, 'metadata>),*
187192
{
188193
fn type_check(specs: &[ColumnSpec]) -> Result<(), TypeCheckError> {
189194
const TUPLE_LEN: usize = (&[$($idx),*] as &[i32]).len();
190195

191196
let column_types_iter = || specs.iter().map(|spec| spec.typ().clone().into_owned());
192197
if let [$($idf),*] = &specs {
193198
$(
194-
<$Ti as DeserializeValue<'frame>>::type_check($idf.typ())
199+
<$Ti as DeserializeValue<'frame, 'metadata>>::type_check($idf.typ())
195200
.map_err(|err| mk_typck_err::<Self>(column_types_iter(), BuiltinTypeCheckErrorKind::ColumnTypeCheckFailed {
196201
column_index: $idx,
197202
column_name: specs[$idx].name().to_owned(),
@@ -206,7 +211,7 @@ macro_rules! impl_tuple {
206211
}
207212
}
208213

209-
fn deserialize(mut row: ColumnIterator<'frame>) -> Result<Self, DeserializationError> {
214+
fn deserialize(mut row: ColumnIterator<'frame, 'metadata>) -> Result<Self, DeserializationError> {
210215
const TUPLE_LEN: usize = (&[$($idx),*] as &[i32]).len();
211216

212217
let ret = (
@@ -217,7 +222,7 @@ macro_rules! impl_tuple {
217222
$idx
218223
)).map_err(deser_error_replace_rust_name::<Self>)?;
219224

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

0 commit comments

Comments
 (0)