1use std::collections::{BTreeMap, HashSet};
7use std::fmt::Display;
8use std::hash::BuildHasher;
9use std::{collections::HashMap, sync::Arc};
10
11use bytes::BufMut;
12use thiserror::Error;
13
14use crate::frame::request::RequestDeserializationError;
15use crate::frame::response::result::ColumnType;
16use crate::frame::response::result::PreparedMetadata;
17use crate::frame::types;
18use crate::frame::{response::result::ColumnSpec, types::RawValue};
19
20use super::value::SerializeValue;
21use super::{CellWriter, RowWriter, SerializationError};
22
23pub struct RowSerializationContext<'a> {
25 pub(crate) columns: &'a [ColumnSpec<'a>],
26}
27
28impl<'a> RowSerializationContext<'a> {
29 #[inline]
31 pub fn from_prepared(prepared: &'a PreparedMetadata) -> Self {
32 Self {
33 columns: prepared.col_specs.as_slice(),
34 }
35 }
36
37 #[inline]
39 pub fn from_specs(specs: &'a [ColumnSpec<'a>]) -> Self {
40 Self { columns: specs }
41 }
42
43 #[inline]
46 pub const fn empty() -> Self {
47 Self { columns: &[] }
48 }
49
50 #[inline]
52 pub fn columns(&self) -> &'a [ColumnSpec<'_>] {
53 self.columns
54 }
55}
56
57pub trait SerializeRow {
64 fn serialize(
69 &self,
70 ctx: &RowSerializationContext<'_>,
71 writer: &mut RowWriter,
72 ) -> Result<(), SerializationError>;
73
74 fn is_empty(&self) -> bool;
82}
83
84macro_rules! impl_serialize_row_for_unit {
85 () => {
86 fn serialize(
87 &self,
88 ctx: &RowSerializationContext<'_>,
89 _writer: &mut RowWriter,
90 ) -> Result<(), SerializationError> {
91 if !ctx.columns().is_empty() {
92 return Err(mk_typck_err::<Self>(
93 BuiltinTypeCheckErrorKind::WrongColumnCount {
94 rust_cols: 0,
95 cql_cols: ctx.columns().len(),
96 },
97 ));
98 }
99 Ok(())
101 }
102
103 #[inline]
104 fn is_empty(&self) -> bool {
105 true
106 }
107 };
108}
109
110impl SerializeRow for () {
111 impl_serialize_row_for_unit!();
112}
113
114impl SerializeRow for [u8; 0] {
115 impl_serialize_row_for_unit!();
116}
117
118macro_rules! impl_serialize_row_for_slice {
119 () => {
120 fn serialize(
121 &self,
122 ctx: &RowSerializationContext<'_>,
123 writer: &mut RowWriter,
124 ) -> Result<(), SerializationError> {
125 if ctx.columns().len() != self.len() {
126 return Err(mk_typck_err::<Self>(
127 BuiltinTypeCheckErrorKind::WrongColumnCount {
128 rust_cols: self.len(),
129 cql_cols: ctx.columns().len(),
130 },
131 ));
132 }
133 for (col, val) in ctx.columns().iter().zip(self.iter()) {
134 $crate::_macro_internal::ser::row::serialize_column::<Self>(val, col, writer)?;
135 }
136 Ok(())
137 }
138
139 #[inline]
140 fn is_empty(&self) -> bool {
141 <[T]>::is_empty(self.as_ref())
142 }
143 };
144}
145
146impl<'a, T: SerializeValue + 'a> SerializeRow for &'a [T] {
147 impl_serialize_row_for_slice!();
148}
149
150impl<T: SerializeValue> SerializeRow for Vec<T> {
151 impl_serialize_row_for_slice!();
152}
153
154impl<T: SerializeRow + ?Sized> SerializeRow for Box<T> {
155 #[inline]
156 fn serialize(
157 &self,
158 ctx: &RowSerializationContext<'_>,
159 writer: &mut RowWriter,
160 ) -> Result<(), SerializationError> {
161 self.as_ref().serialize(ctx, writer)
162 }
163
164 #[inline]
165 fn is_empty(&self) -> bool {
166 self.as_ref().is_empty()
167 }
168}
169
170macro_rules! impl_serialize_row_for_map {
171 () => {
172 fn serialize(
173 &self,
174 ctx: &RowSerializationContext<'_>,
175 writer: &mut RowWriter,
176 ) -> Result<(), SerializationError> {
177 let mut unused_columns: HashSet<&str> = self.keys().map(|k| k.as_ref()).collect();
181
182 for col in ctx.columns.iter() {
183 match self.get(col.name()) {
184 None => {
185 return Err(mk_typck_err::<Self>(
186 BuiltinTypeCheckErrorKind::ValueMissingForColumn {
187 name: col.name().to_owned(),
188 },
189 ));
190 }
191 Some(v) => {
192 $crate::_macro_internal::ser::row::serialize_column::<Self>(
193 v, col, writer,
194 )?;
195 let _ = unused_columns.remove(col.name());
196 }
197 }
198 }
199
200 if !unused_columns.is_empty() {
201 let name = unused_columns.iter().min().unwrap();
203 return Err(mk_typck_err::<Self>(
204 BuiltinTypeCheckErrorKind::NoColumnWithName {
205 name: name.to_string(),
206 },
207 ));
208 }
209
210 Ok(())
211 }
212
213 #[inline]
214 fn is_empty(&self) -> bool {
215 Self::is_empty(self)
216 }
217 };
218}
219
220impl<T: SerializeValue> SerializeRow for BTreeMap<String, T> {
221 impl_serialize_row_for_map!();
222}
223
224impl<T: SerializeValue> SerializeRow for BTreeMap<&str, T> {
225 impl_serialize_row_for_map!();
226}
227
228impl<T: SerializeValue, S: BuildHasher> SerializeRow for HashMap<String, T, S> {
229 impl_serialize_row_for_map!();
230}
231
232impl<T: SerializeValue, S: BuildHasher> SerializeRow for HashMap<&str, T, S> {
233 impl_serialize_row_for_map!();
234}
235
236impl<T: SerializeRow + ?Sized> SerializeRow for &T {
237 fn serialize(
238 &self,
239 ctx: &RowSerializationContext<'_>,
240 writer: &mut RowWriter,
241 ) -> Result<(), SerializationError> {
242 <T as SerializeRow>::serialize(self, ctx, writer)
243 }
244
245 #[inline]
246 fn is_empty(&self) -> bool {
247 <T as SerializeRow>::is_empty(self)
248 }
249}
250
251macro_rules! impl_tuple {
252 (
253 $($typs:ident),*;
254 $($fidents:ident),*;
255 $($tidents:ident),*;
256 $length:expr
257 ) => {
258 impl<$($typs: SerializeValue),*> SerializeRow for ($($typs,)*) {
259 fn serialize(
260 &self,
261 ctx: &RowSerializationContext<'_>,
262 writer: &mut RowWriter,
263 ) -> Result<(), SerializationError> {
264 let ($($tidents,)*) = match ctx.columns() {
265 [$($tidents),*] => ($($tidents,)*),
266 _ => return Err(mk_typck_err::<Self>(
267 BuiltinTypeCheckErrorKind::WrongColumnCount {
268 rust_cols: $length,
269 cql_cols: ctx.columns().len(),
270 },
271 )),
272 };
273 let ($($fidents,)*) = self;
274 $(
275 $crate::_macro_internal::ser::row::serialize_column::<Self>($fidents, $tidents, writer)?;
276 )*
277 Ok(())
278 }
279
280 #[inline]
281 fn is_empty(&self) -> bool {
282 $length == 0
283 }
284 }
285 };
286}
287
288macro_rules! impl_tuples {
289 (;;;$length:expr) => {};
290 (
291 $typ:ident$(, $($typs:ident),*)?;
292 $fident:ident$(, $($fidents:ident),*)?;
293 $tident:ident$(, $($tidents:ident),*)?;
294 $length:expr
295 ) => {
296 impl_tuples!(
297 $($($typs),*)?;
298 $($($fidents),*)?;
299 $($($tidents),*)?;
300 $length - 1
301 );
302 impl_tuple!(
303 $typ$(, $($typs),*)?;
304 $fident$(, $($fidents),*)?;
305 $tident$(, $($tidents),*)?;
306 $length
307 );
308 };
309}
310
311impl_tuples!(
312 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15;
313 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15;
314 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15;
315 16
316);
317
318#[derive(Debug, Error, Clone)]
321#[error("Failed to type check query arguments {rust_name}: {kind}")]
322pub struct BuiltinTypeCheckError {
323 pub rust_name: &'static str,
325
326 pub kind: BuiltinTypeCheckErrorKind,
328}
329
330#[doc(hidden)]
331pub fn mk_typck_err<T>(kind: impl Into<BuiltinTypeCheckErrorKind>) -> SerializationError {
332 mk_typck_err_named(std::any::type_name::<T>(), kind)
333}
334
335fn mk_typck_err_named(
336 name: &'static str,
337 kind: impl Into<BuiltinTypeCheckErrorKind>,
338) -> SerializationError {
339 SerializationError::new(BuiltinTypeCheckError {
340 rust_name: name,
341 kind: kind.into(),
342 })
343}
344
345#[derive(Debug, Error, Clone)]
348#[error("Failed to serialize query arguments {rust_name}: {kind}")]
349pub struct BuiltinSerializationError {
350 pub rust_name: &'static str,
352
353 pub kind: BuiltinSerializationErrorKind,
355}
356
357pub(crate) fn mk_ser_err<T>(kind: impl Into<BuiltinSerializationErrorKind>) -> SerializationError {
358 mk_ser_err_named(std::any::type_name::<T>(), kind)
359}
360
361fn mk_ser_err_named(
362 name: &'static str,
363 kind: impl Into<BuiltinSerializationErrorKind>,
364) -> SerializationError {
365 SerializationError::new(BuiltinSerializationError {
366 rust_name: name,
367 kind: kind.into(),
368 })
369}
370
371#[derive(Debug, Clone)]
373#[non_exhaustive]
374pub enum BuiltinTypeCheckErrorKind {
375 WrongColumnCount {
377 rust_cols: usize,
379
380 cql_cols: usize,
382 },
383
384 NoColumnWithName {
387 name: String,
389 },
390
391 ValueMissingForColumn {
393 name: String,
396 },
397
398 ColumnNameMismatch {
400 rust_column_name: String,
402
403 db_column_name: String,
405 },
406}
407
408impl Display for BuiltinTypeCheckErrorKind {
409 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
410 match self {
411 BuiltinTypeCheckErrorKind::WrongColumnCount {
412 rust_cols,
413 cql_cols,
414 } => {
415 write!(
416 f,
417 "wrong column count: the statement operates on {cql_cols} columns, but the given rust type provides {rust_cols}"
418 )
419 }
420 BuiltinTypeCheckErrorKind::NoColumnWithName { name } => {
421 write!(
422 f,
423 "value for column {name} was provided, but there is no bind marker for this column in the query"
424 )
425 }
426 BuiltinTypeCheckErrorKind::ValueMissingForColumn { name } => {
427 write!(
428 f,
429 "value for column {name} was not provided, but the query requires it"
430 )
431 }
432 BuiltinTypeCheckErrorKind::ColumnNameMismatch {
433 rust_column_name,
434 db_column_name,
435 } => write!(
436 f,
437 "expected column with name {db_column_name} at given position, but the Rust field name is {rust_column_name}"
438 ),
439 }
440 }
441}
442
443#[derive(Debug, Clone)]
445#[non_exhaustive]
446pub enum BuiltinSerializationErrorKind {
447 ColumnSerializationFailed {
449 name: String,
451
452 err: SerializationError,
454 },
455 TooManyValues,
457}
458
459impl Display for BuiltinSerializationErrorKind {
460 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
461 match self {
462 BuiltinSerializationErrorKind::ColumnSerializationFailed { name, err } => {
463 write!(f, "failed to serialize column {name}: {err}")
464 }
465 BuiltinSerializationErrorKind::TooManyValues => {
466 write!(
467 f,
468 "Too many values to add, max 65,535 values can be sent in a request"
469 )
470 }
471 }
472 }
473}
474
475#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
483pub struct SerializedValues {
484 serialized_values: Vec<u8>,
485 element_count: u16,
486}
487
488impl SerializedValues {
489 pub const fn new() -> Self {
491 SerializedValues {
492 serialized_values: Vec::new(),
493 element_count: 0,
494 }
495 }
496
497 pub const EMPTY: &'static SerializedValues = &SerializedValues::new();
499
500 pub fn from_serializable<T: SerializeRow + ?Sized>(
502 ctx: &RowSerializationContext,
503 row: &T,
504 ) -> Result<Self, SerializationError> {
505 Self::from_closure(|writer| row.serialize(ctx, writer)).map(|(sr, _)| sr)
506 }
507
508 pub fn from_closure<F, R>(f: F) -> Result<(Self, R), SerializationError>
510 where
511 F: FnOnce(&mut RowWriter) -> Result<R, SerializationError>,
512 {
513 let mut data = Vec::new();
514 let mut writer = RowWriter::new(&mut data);
515 let ret = f(&mut writer)?;
516 let element_count = match writer.value_count().try_into() {
517 Ok(n) => n,
518 Err(_) => {
519 return Err(SerializationError(Arc::new(mk_ser_err::<Self>(
520 BuiltinSerializationErrorKind::TooManyValues,
521 ))));
522 }
523 };
524
525 Ok((
526 SerializedValues {
527 serialized_values: data,
528 element_count,
529 },
530 ret,
531 ))
532 }
533
534 #[inline]
536 pub fn is_empty(&self) -> bool {
537 self.element_count() == 0
538 }
539
540 #[inline]
542 pub fn iter(&self) -> impl Iterator<Item = RawValue<'_>> {
543 SerializedValuesIterator {
544 serialized_values: &self.serialized_values,
545 }
546 }
547
548 #[inline]
550 pub fn element_count(&self) -> u16 {
551 self.element_count
552 }
553
554 #[inline]
556 pub fn buffer_size(&self) -> usize {
557 self.serialized_values.len()
558 }
559
560 pub(crate) fn write_to_request(&self, buf: &mut impl BufMut) {
561 buf.put_u16(self.element_count);
562 buf.put(self.serialized_values.as_slice())
563 }
564
565 pub(crate) fn get_contents(&self) -> &[u8] {
567 &self.serialized_values
568 }
569
570 pub fn add_value<T: SerializeValue>(
572 &mut self,
573 val: &T,
574 typ: &ColumnType,
575 ) -> Result<(), SerializationError> {
576 if self.element_count() == u16::MAX {
577 return Err(SerializationError(Arc::new(mk_ser_err::<Self>(
578 BuiltinSerializationErrorKind::TooManyValues,
579 ))));
580 }
581
582 let len_before_serialize: usize = self.serialized_values.len();
583
584 let writer = CellWriter::new(&mut self.serialized_values);
585 if let Err(e) = val.serialize(typ, writer) {
586 self.serialized_values.resize(len_before_serialize, 0);
587 Err(e)
588 } else {
589 self.element_count += 1;
590 Ok(())
591 }
592 }
593
594 pub(crate) fn new_from_frame(buf: &mut &[u8]) -> Result<Self, RequestDeserializationError> {
597 let values_num = types::read_short(buf)?;
598 let values_beg = *buf;
599 for _ in 0..values_num {
600 let _serialized = types::read_value(buf)?;
601 }
602
603 let values_len_in_buf = values_beg.len() - buf.len();
604 let values_in_frame = &values_beg[0..values_len_in_buf];
605 Ok(SerializedValues {
606 serialized_values: values_in_frame.to_vec(),
607 element_count: values_num,
608 })
609 }
610}
611
612impl Default for SerializedValues {
613 fn default() -> Self {
614 Self::new()
615 }
616}
617
618#[derive(Clone, Copy)]
620pub struct SerializedValuesIterator<'a> {
621 serialized_values: &'a [u8],
622}
623
624impl<'a> Iterator for SerializedValuesIterator<'a> {
625 type Item = RawValue<'a>;
626
627 fn next(&mut self) -> Option<Self::Item> {
628 if self.serialized_values.is_empty() {
629 return None;
630 }
631
632 Some(types::read_value(&mut self.serialized_values).expect("badly encoded value"))
633 }
634}
635
636mod doctests {
637
638 fn _test_struct_deserialization_name_check_skip_requires_enforce_order() {}
645
646 fn _test_struct_deserialization_skip_name_check_conflicts_with_rename() {}
656
657 fn _test_struct_deserialization_skip_rename_collision_with_field() {}
668
669 fn _test_struct_deserialization_rename_collision_with_another_rename() {}
681}
682
683#[cfg(test)]
684#[path = "row_tests.rs"]
685pub(crate) mod tests;