Skip to content

Commit c458b6a

Browse files
wprzytulapiodul
andcommitted
deser/result: introduce TypedRowIterator
This iterator wraps over RowIterator and for each row consumes the ColumnIterator and deserializes the given type. Co-authored-by: Piotr Dulikowski <[email protected]>
1 parent da357cf commit c458b6a

File tree

1 file changed

+88
-3
lines changed

1 file changed

+88
-3
lines changed

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

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::frame::response::result::ColumnSpec;
22

3-
use super::row::{mk_deser_err, BuiltinDeserializationErrorKind, ColumnIterator};
4-
use super::{DeserializationError, FrameSlice};
3+
use super::row::{mk_deser_err, BuiltinDeserializationErrorKind, ColumnIterator, DeserializeRow};
4+
use super::{DeserializationError, FrameSlice, TypeCheckError};
5+
use std::marker::PhantomData;
56

67
/// Iterates over the whole result, returning rows.
78
pub struct RowIterator<'frame> {
@@ -73,12 +74,70 @@ impl<'frame> Iterator for RowIterator<'frame> {
7374
}
7475
}
7576

77+
/// A typed version of [RowIterator] which deserializes the rows before
78+
/// returning them.
79+
pub struct TypedRowIterator<'frame, R> {
80+
inner: RowIterator<'frame>,
81+
_phantom: PhantomData<R>,
82+
}
83+
84+
impl<'frame, R> TypedRowIterator<'frame, R>
85+
where
86+
R: DeserializeRow<'frame>,
87+
{
88+
/// Creates a new [TypedRowIterator] from given [RowIterator].
89+
///
90+
/// Calls `R::type_check` and fails if the type check fails.
91+
#[inline]
92+
pub fn new(raw: RowIterator<'frame>) -> Result<Self, TypeCheckError> {
93+
R::type_check(raw.specs())?;
94+
Ok(Self {
95+
inner: raw,
96+
_phantom: PhantomData,
97+
})
98+
}
99+
100+
/// Returns information about the columns of rows that are iterated over.
101+
#[inline]
102+
pub fn specs(&self) -> &'frame [ColumnSpec] {
103+
self.inner.specs()
104+
}
105+
106+
/// Returns the remaining number of rows that this iterator is supposed
107+
/// to return.
108+
#[inline]
109+
pub fn rows_remaining(&self) -> usize {
110+
self.inner.rows_remaining()
111+
}
112+
}
113+
114+
impl<'frame, R> Iterator for TypedRowIterator<'frame, R>
115+
where
116+
R: DeserializeRow<'frame>,
117+
{
118+
type Item = Result<R, DeserializationError>;
119+
120+
#[inline]
121+
fn next(&mut self) -> Option<Self::Item> {
122+
self.inner
123+
.next()
124+
.map(|raw| raw.and_then(|raw| R::deserialize(raw)))
125+
}
126+
127+
#[inline]
128+
fn size_hint(&self) -> (usize, Option<usize>) {
129+
self.inner.size_hint()
130+
}
131+
}
132+
76133
#[cfg(test)]
77134
mod tests {
135+
use bytes::Bytes;
136+
78137
use crate::frame::response::result::ColumnType;
79138

80139
use super::super::tests::{serialize_cells, spec, CELL1, CELL2};
81-
use super::{FrameSlice, RowIterator};
140+
use super::{FrameSlice, RowIterator, TypedRowIterator};
82141

83142
#[test]
84143
fn test_row_iterator_basic_parse() {
@@ -112,4 +171,30 @@ mod tests {
112171
iter.next().unwrap().unwrap();
113172
assert!(iter.next().unwrap().is_err());
114173
}
174+
175+
#[test]
176+
fn test_typed_row_iterator_basic_parse() {
177+
let raw_data = serialize_cells([Some(CELL1), Some(CELL2), Some(CELL2), Some(CELL1)]);
178+
let specs = [spec("b1", ColumnType::Blob), spec("b2", ColumnType::Blob)];
179+
let iter = RowIterator::new(2, &specs, FrameSlice::new(&raw_data));
180+
let mut iter = TypedRowIterator::<'_, (&[u8], Vec<u8>)>::new(iter).unwrap();
181+
182+
let (c11, c12) = iter.next().unwrap().unwrap();
183+
assert_eq!(c11, CELL1);
184+
assert_eq!(c12, CELL2);
185+
186+
let (c21, c22) = iter.next().unwrap().unwrap();
187+
assert_eq!(c21, CELL2);
188+
assert_eq!(c22, CELL1);
189+
190+
assert!(iter.next().is_none());
191+
}
192+
193+
#[test]
194+
fn test_typed_row_iterator_wrong_type() {
195+
let raw_data = Bytes::new();
196+
let specs = [spec("b1", ColumnType::Blob), spec("b2", ColumnType::Blob)];
197+
let iter = RowIterator::new(0, &specs, FrameSlice::new(&raw_data));
198+
assert!(TypedRowIterator::<'_, (i32, i64)>::new(iter).is_err());
199+
}
115200
}

0 commit comments

Comments
 (0)