scylla_cql/serialize/
raw_batch.rs

1//! Contains the [`RawBatchValues`] and [`RawBatchValuesIterator`] trait and their
2//! implementations.
3
4use super::batch::{BatchValues, BatchValuesIterator};
5use super::row::{RowSerializationContext, SerializedValues};
6use super::{RowWriter, SerializationError};
7
8/// Represents a list of sets of values for a batch statement.
9///
10/// Unlike [`BatchValues`]), it doesn't require type
11/// information from the statements of the batch in order to be serialized.
12///
13/// This is a lower level trait than [`BatchValues`])
14/// and is only used for interaction between the code in `scylla` and
15/// `scylla-cql` crates. If you are a regular user of the driver, you shouldn't
16/// care about this trait at all.
17pub trait RawBatchValues {
18    /// An `Iterator`-like object over the values from the parent `BatchValues` object.
19    // For some unknown reason, this type, when not resolved to a concrete type for a given async function,
20    // cannot live across await boundaries while maintaining the corresponding future `Send`, unless `'r: 'static`
21    //
22    // See <https://github.com/scylladb/scylla-rust-driver/issues/599> for more details
23    type RawBatchValuesIter<'r>: RawBatchValuesIterator<'r>
24    where
25        Self: 'r;
26
27    /// Returns an iterator over the data contained in this object.
28    fn batch_values_iter(&self) -> Self::RawBatchValuesIter<'_>;
29}
30
31/// An `Iterator`-like object over the values from the parent [`RawBatchValues`] object.
32///
33/// It's not a true [`Iterator`] because it does not provide direct access to the
34/// items being iterated over, instead it allows calling methods of the underlying
35/// [`SerializeRow`](super::row::SerializeRow) trait while advancing the iterator.
36///
37/// Unlike [`BatchValuesIterator`], it doesn't
38/// need type information for serialization.
39pub trait RawBatchValuesIterator<'a> {
40    /// Serializes the next set of values in the sequence and advances the iterator.
41    fn serialize_next(&mut self, writer: &mut RowWriter) -> Option<Result<(), SerializationError>>;
42
43    /// Returns whether the next set of values is empty or not and advances the iterator.
44    fn is_empty_next(&mut self) -> Option<bool>;
45
46    /// Skips the next set of values.
47    fn skip_next(&mut self) -> Option<()>;
48
49    /// Return the number of sets of values, consuming the iterator in the process.
50    #[inline]
51    fn count(mut self) -> usize
52    where
53        Self: Sized,
54    {
55        std::iter::from_fn(|| self.skip_next()).count()
56    }
57}
58
59// An implementation used by `scylla-proxy`
60impl RawBatchValues for Vec<SerializedValues> {
61    type RawBatchValuesIter<'r>
62        = std::slice::Iter<'r, SerializedValues>
63    where
64        Self: 'r;
65
66    fn batch_values_iter(&self) -> Self::RawBatchValuesIter<'_> {
67        self.iter()
68    }
69}
70
71impl<'r> RawBatchValuesIterator<'r> for std::slice::Iter<'r, SerializedValues> {
72    #[inline]
73    fn serialize_next(&mut self, writer: &mut RowWriter) -> Option<Result<(), SerializationError>> {
74        self.next().map(|sv| {
75            writer.append_serialize_row(sv);
76            Ok(())
77        })
78    }
79
80    fn is_empty_next(&mut self) -> Option<bool> {
81        self.next().map(|sv| sv.is_empty())
82    }
83
84    #[inline]
85    fn skip_next(&mut self) -> Option<()> {
86        self.next().map(|_| ())
87    }
88
89    #[inline]
90    fn count(self) -> usize {
91        <_ as Iterator>::count(self)
92    }
93}
94
95/// Takes `BatchValues` and an iterator over contexts, and turns them into a `RawBatchValues`.
96pub struct RawBatchValuesAdapter<BV, CTX> {
97    batch_values: BV,
98    contexts: CTX,
99}
100
101impl<BV, CTX> RawBatchValuesAdapter<BV, CTX> {
102    /// Creates a new `RawBatchValuesAdapter` object.
103    #[inline]
104    pub fn new(batch_values: BV, contexts: CTX) -> Self {
105        Self {
106            batch_values,
107            contexts,
108        }
109    }
110}
111
112impl<'ctx, BV, CTX> RawBatchValues for RawBatchValuesAdapter<BV, CTX>
113where
114    BV: BatchValues,
115    CTX: Iterator<Item = RowSerializationContext<'ctx>> + Clone,
116{
117    type RawBatchValuesIter<'r>
118        = RawBatchValuesIteratorAdapter<BV::BatchValuesIter<'r>, CTX>
119    where
120        Self: 'r;
121
122    #[inline]
123    fn batch_values_iter(&self) -> Self::RawBatchValuesIter<'_> {
124        RawBatchValuesIteratorAdapter {
125            batch_values_iterator: self.batch_values.batch_values_iter(),
126            contexts: self.contexts.clone(),
127        }
128    }
129}
130
131/// Takes `BatchValuesIterator` and an iterator over contexts, and turns them into a `RawBatchValuesIterator`.
132pub struct RawBatchValuesIteratorAdapter<BVI, CTX> {
133    batch_values_iterator: BVI,
134    contexts: CTX,
135}
136
137impl<'bvi, 'ctx, BVI, CTX> RawBatchValuesIterator<'bvi> for RawBatchValuesIteratorAdapter<BVI, CTX>
138where
139    BVI: BatchValuesIterator<'bvi>,
140    CTX: Iterator<Item = RowSerializationContext<'ctx>>,
141{
142    #[inline]
143    fn serialize_next(&mut self, writer: &mut RowWriter) -> Option<Result<(), SerializationError>> {
144        // We do `unwrap_or` because we want the iterator length to be the same
145        // as the amount of values. Limiting to length of the amount of
146        // statements (contexts) causes the caller to not be able to correctly
147        // detect that amount of statements and values is different.
148        let ctx = self
149            .contexts
150            .next()
151            .unwrap_or(RowSerializationContext::empty());
152        self.batch_values_iterator.serialize_next(&ctx, writer)
153    }
154
155    fn is_empty_next(&mut self) -> Option<bool> {
156        let _ = self.contexts.next();
157        let ret = self.batch_values_iterator.is_empty_next()?;
158        Some(ret)
159    }
160
161    #[inline]
162    fn skip_next(&mut self) -> Option<()> {
163        let _ = self.contexts.next();
164        self.batch_values_iterator.skip_next()?;
165        Some(())
166    }
167}