1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7use std::fmt::Display;
8use std::hash::BuildHasher;
9use std::net::IpAddr;
10use std::ops::Deref as _;
11use std::sync::Arc;
12
13use thiserror::Error;
14use uuid::Uuid;
15
16use crate::frame::response::result::{CollectionType, ColumnType, NativeType};
17use crate::frame::types::vint_encode;
18use crate::value::{
19 Counter, CqlDate, CqlDecimal, CqlDecimalBorrowed, CqlDuration, CqlTime, CqlTimestamp,
20 CqlTimeuuid, CqlValue, CqlVarint, CqlVarintBorrowed, MaybeUnset, Unset,
21};
22
23#[cfg(feature = "chrono-04")]
24use crate::value::ValueOverflow;
25
26use super::writers::WrittenCellProof;
27use super::{CellWriter, SerializationError};
28
29pub trait SerializeValue {
36 fn serialize<'b>(
52 &self,
53 typ: &ColumnType,
54 writer: CellWriter<'b>,
55 ) -> Result<WrittenCellProof<'b>, SerializationError>;
56}
57
58macro_rules! exact_type_check {
59 ($typ:ident, $($cql:tt),*) => {
60 match $typ {
61 $(ColumnType::Native(NativeType::$cql))|* => {},
62 _ => return Err(mk_typck_err::<Self>(
63 $typ,
64 BuiltinTypeCheckErrorKind::MismatchedType {
65 expected: &[$(ColumnType::Native(NativeType::$cql)),*],
66 }
67 ))
68 }
69 };
70}
71
72macro_rules! impl_serialize_via_writer {
73 (|$me:ident, $writer:ident| $e:expr) => {
74 impl_serialize_via_writer!(|$me, _typ, $writer| $e);
75 };
76 (|$me:ident, $typ:ident, $writer:ident| $e:expr) => {
77 fn serialize<'b>(
78 &self,
79 typ: &ColumnType,
80 writer: CellWriter<'b>,
81 ) -> Result<WrittenCellProof<'b>, SerializationError> {
82 let $writer = writer;
83 let $typ = typ;
84 let $me = self;
85 let proof = $e;
86 Ok(proof)
87 }
88 };
89}
90
91impl SerializeValue for i8 {
92 impl_serialize_via_writer!(|me, typ, writer| {
93 exact_type_check!(typ, TinyInt);
94 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
95 });
96}
97impl SerializeValue for i16 {
98 impl_serialize_via_writer!(|me, typ, writer| {
99 exact_type_check!(typ, SmallInt);
100 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
101 });
102}
103impl SerializeValue for i32 {
104 impl_serialize_via_writer!(|me, typ, writer| {
105 exact_type_check!(typ, Int);
106 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
107 });
108}
109impl SerializeValue for i64 {
110 impl_serialize_via_writer!(|me, typ, writer| {
111 exact_type_check!(typ, BigInt);
112 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
113 });
114}
115impl SerializeValue for CqlDecimal {
116 impl_serialize_via_writer!(|me, typ, writer| {
117 exact_type_check!(typ, Decimal);
118 let mut builder = writer.into_value_builder();
119 let (bytes, scale) = me.as_signed_be_bytes_slice_and_exponent();
120 builder.append_bytes(&scale.to_be_bytes());
121 builder.append_bytes(bytes);
122 builder
123 .finish()
124 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
125 });
126}
127impl SerializeValue for CqlDecimalBorrowed<'_> {
128 impl_serialize_via_writer!(|me, typ, writer| {
129 exact_type_check!(typ, Decimal);
130 let mut builder = writer.into_value_builder();
131 let (bytes, scale) = me.as_signed_be_bytes_slice_and_exponent();
132 builder.append_bytes(&scale.to_be_bytes());
133 builder.append_bytes(bytes);
134 builder
135 .finish()
136 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
137 });
138}
139#[cfg(feature = "bigdecimal-04")]
140impl SerializeValue for bigdecimal_04::BigDecimal {
141 impl_serialize_via_writer!(|me, typ, writer| {
142 exact_type_check!(typ, Decimal);
143 let mut builder = writer.into_value_builder();
144 let (value, scale) = me.as_bigint_and_exponent();
145 let scale: i32 = scale
146 .try_into()
147 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::ValueOverflow))?;
148 builder.append_bytes(&scale.to_be_bytes());
149 builder.append_bytes(&value.to_signed_bytes_be());
150 builder
151 .finish()
152 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
153 });
154}
155impl SerializeValue for CqlDate {
156 impl_serialize_via_writer!(|me, typ, writer| {
157 exact_type_check!(typ, Date);
158 writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
159 });
160}
161impl SerializeValue for CqlTimestamp {
162 impl_serialize_via_writer!(|me, typ, writer| {
163 exact_type_check!(typ, Timestamp);
164 writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
165 });
166}
167impl SerializeValue for CqlTime {
168 impl_serialize_via_writer!(|me, typ, writer| {
169 exact_type_check!(typ, Time);
170 writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
171 });
172}
173#[cfg(feature = "chrono-04")]
174impl SerializeValue for chrono_04::NaiveDate {
175 impl_serialize_via_writer!(|me, typ, writer| {
176 exact_type_check!(typ, Date);
177 <CqlDate as SerializeValue>::serialize(&(*me).into(), typ, writer)?
178 });
179}
180#[cfg(feature = "chrono-04")]
181impl SerializeValue for chrono_04::DateTime<chrono_04::Utc> {
182 impl_serialize_via_writer!(|me, typ, writer| {
183 exact_type_check!(typ, Timestamp);
184 <CqlTimestamp as SerializeValue>::serialize(&(*me).into(), typ, writer)?
185 });
186}
187#[cfg(feature = "chrono-04")]
188impl SerializeValue for chrono_04::NaiveTime {
189 impl_serialize_via_writer!(|me, typ, writer| {
190 exact_type_check!(typ, Time);
191 let cql_time = CqlTime::try_from(*me).map_err(|_: ValueOverflow| {
192 mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::ValueOverflow)
193 })?;
194 <CqlTime as SerializeValue>::serialize(&cql_time, typ, writer)?
195 });
196}
197#[cfg(feature = "time-03")]
198impl SerializeValue for time_03::Date {
199 impl_serialize_via_writer!(|me, typ, writer| {
200 exact_type_check!(typ, Date);
201 <CqlDate as SerializeValue>::serialize(&(*me).into(), typ, writer)?
202 });
203}
204#[cfg(feature = "time-03")]
205impl SerializeValue for time_03::OffsetDateTime {
206 impl_serialize_via_writer!(|me, typ, writer| {
207 exact_type_check!(typ, Timestamp);
208 <CqlTimestamp as SerializeValue>::serialize(&(*me).into(), typ, writer)?
209 });
210}
211#[cfg(feature = "time-03")]
212impl SerializeValue for time_03::Time {
213 impl_serialize_via_writer!(|me, typ, writer| {
214 exact_type_check!(typ, Time);
215 <CqlTime as SerializeValue>::serialize(&(*me).into(), typ, writer)?
216 });
217}
218#[cfg(feature = "secrecy-08")]
219impl<V: SerializeValue + secrecy_08::Zeroize> SerializeValue for secrecy_08::Secret<V> {
220 fn serialize<'b>(
221 &self,
222 typ: &ColumnType,
223 writer: CellWriter<'b>,
224 ) -> Result<WrittenCellProof<'b>, SerializationError> {
225 use secrecy_08::ExposeSecret;
226 V::serialize(self.expose_secret(), typ, writer)
227 }
228}
229impl SerializeValue for bool {
230 impl_serialize_via_writer!(|me, typ, writer| {
231 exact_type_check!(typ, Boolean);
232 writer.set_value(&[*me as u8]).unwrap()
233 });
234}
235impl SerializeValue for f32 {
236 impl_serialize_via_writer!(|me, typ, writer| {
237 exact_type_check!(typ, Float);
238 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
239 });
240}
241impl SerializeValue for f64 {
242 impl_serialize_via_writer!(|me, typ, writer| {
243 exact_type_check!(typ, Double);
244 writer.set_value(me.to_be_bytes().as_slice()).unwrap()
245 });
246}
247impl SerializeValue for Uuid {
248 impl_serialize_via_writer!(|me, typ, writer| {
249 exact_type_check!(typ, Uuid);
250 writer.set_value(me.as_bytes().as_ref()).unwrap()
251 });
252}
253impl SerializeValue for CqlTimeuuid {
254 impl_serialize_via_writer!(|me, typ, writer| {
255 exact_type_check!(typ, Timeuuid);
256 writer.set_value(me.as_bytes().as_ref()).unwrap()
257 });
258}
259impl SerializeValue for CqlVarint {
260 impl_serialize_via_writer!(|me, typ, writer| {
261 exact_type_check!(typ, Varint);
262 writer
263 .set_value(me.as_signed_bytes_be_slice())
264 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
265 });
266}
267impl SerializeValue for CqlVarintBorrowed<'_> {
268 impl_serialize_via_writer!(|me, typ, writer| {
269 exact_type_check!(typ, Varint);
270 writer
271 .set_value(me.as_signed_bytes_be_slice())
272 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
273 });
274}
275#[cfg(feature = "num-bigint-03")]
276impl SerializeValue for num_bigint_03::BigInt {
277 impl_serialize_via_writer!(|me, typ, writer| {
278 exact_type_check!(typ, Varint);
279 writer
283 .set_value(me.to_signed_bytes_be().as_slice())
284 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
285 });
286}
287#[cfg(feature = "num-bigint-04")]
288impl SerializeValue for num_bigint_04::BigInt {
289 impl_serialize_via_writer!(|me, typ, writer| {
290 exact_type_check!(typ, Varint);
291 writer
293 .set_value(me.to_signed_bytes_be().as_slice())
294 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
295 });
296}
297impl SerializeValue for &str {
298 impl_serialize_via_writer!(|me, typ, writer| {
299 exact_type_check!(typ, Ascii, Text);
300 writer
301 .set_value(me.as_bytes())
302 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
303 });
304}
305impl SerializeValue for Vec<u8> {
306 impl_serialize_via_writer!(|me, typ, writer| {
307 exact_type_check!(typ, Blob);
308 writer
309 .set_value(me.as_ref())
310 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
311 });
312}
313impl SerializeValue for &[u8] {
314 impl_serialize_via_writer!(|me, typ, writer| {
315 exact_type_check!(typ, Blob);
316 writer
317 .set_value(me)
318 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
319 });
320}
321impl<const N: usize> SerializeValue for [u8; N] {
322 impl_serialize_via_writer!(|me, typ, writer| {
323 exact_type_check!(typ, Blob);
324 writer
325 .set_value(me.as_ref())
326 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
327 });
328}
329impl SerializeValue for IpAddr {
330 impl_serialize_via_writer!(|me, typ, writer| {
331 exact_type_check!(typ, Inet);
332 match me {
333 IpAddr::V4(ip) => writer.set_value(&ip.octets()).unwrap(),
334 IpAddr::V6(ip) => writer.set_value(&ip.octets()).unwrap(),
335 }
336 });
337}
338impl SerializeValue for String {
339 impl_serialize_via_writer!(|me, typ, writer| {
340 exact_type_check!(typ, Ascii, Text);
341 writer
342 .set_value(me.as_bytes())
343 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
344 });
345}
346impl<T: SerializeValue> SerializeValue for Option<T> {
347 fn serialize<'b>(
348 &self,
349 typ: &ColumnType,
350 writer: CellWriter<'b>,
351 ) -> Result<WrittenCellProof<'b>, SerializationError> {
352 match self {
353 Some(v) => v.serialize(typ, writer),
354 None => Ok(writer.set_null()),
355 }
356 }
357}
358impl SerializeValue for Unset {
359 impl_serialize_via_writer!(|_me, writer| writer.set_unset());
360}
361impl SerializeValue for Counter {
362 impl_serialize_via_writer!(|me, typ, writer| {
363 exact_type_check!(typ, Counter);
364 writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
365 });
366}
367impl SerializeValue for CqlDuration {
368 impl_serialize_via_writer!(|me, typ, writer| {
369 exact_type_check!(typ, Duration);
370 let mut buf = Vec::with_capacity(27); vint_encode(me.months as i64, &mut buf);
373 vint_encode(me.days as i64, &mut buf);
374 vint_encode(me.nanoseconds, &mut buf);
375 writer.set_value(buf.as_slice()).unwrap()
376 });
377}
378impl<V: SerializeValue> SerializeValue for MaybeUnset<V> {
379 fn serialize<'b>(
380 &self,
381 typ: &ColumnType,
382 writer: CellWriter<'b>,
383 ) -> Result<WrittenCellProof<'b>, SerializationError> {
384 match self {
385 MaybeUnset::Set(v) => v.serialize(typ, writer),
386 MaybeUnset::Unset => Ok(writer.set_unset()),
387 }
388 }
389}
390impl<T: SerializeValue + ?Sized> SerializeValue for &T {
391 fn serialize<'b>(
392 &self,
393 typ: &ColumnType,
394 writer: CellWriter<'b>,
395 ) -> Result<WrittenCellProof<'b>, SerializationError> {
396 T::serialize(*self, typ, writer)
397 }
398}
399impl<T: SerializeValue + ?Sized> SerializeValue for Box<T> {
400 fn serialize<'b>(
401 &self,
402 typ: &ColumnType,
403 writer: CellWriter<'b>,
404 ) -> Result<WrittenCellProof<'b>, SerializationError> {
405 T::serialize(&**self, typ, writer)
406 }
407}
408impl<V: SerializeValue, S: BuildHasher + Default> SerializeValue for HashSet<V, S> {
409 fn serialize<'b>(
410 &self,
411 typ: &ColumnType,
412 writer: CellWriter<'b>,
413 ) -> Result<WrittenCellProof<'b>, SerializationError> {
414 serialize_sequence(
415 std::any::type_name::<Self>(),
416 self.len(),
417 self.iter(),
418 typ,
419 writer,
420 )
421 }
422}
423impl<K: SerializeValue, V: SerializeValue, S: BuildHasher> SerializeValue for HashMap<K, V, S> {
424 fn serialize<'b>(
425 &self,
426 typ: &ColumnType,
427 writer: CellWriter<'b>,
428 ) -> Result<WrittenCellProof<'b>, SerializationError> {
429 serialize_mapping(
430 std::any::type_name::<Self>(),
431 self.len(),
432 self.iter(),
433 typ,
434 writer,
435 )
436 }
437}
438impl<V: SerializeValue> SerializeValue for BTreeSet<V> {
439 fn serialize<'b>(
440 &self,
441 typ: &ColumnType,
442 writer: CellWriter<'b>,
443 ) -> Result<WrittenCellProof<'b>, SerializationError> {
444 serialize_sequence(
445 std::any::type_name::<Self>(),
446 self.len(),
447 self.iter(),
448 typ,
449 writer,
450 )
451 }
452}
453impl<K: SerializeValue, V: SerializeValue> SerializeValue for BTreeMap<K, V> {
454 fn serialize<'b>(
455 &self,
456 typ: &ColumnType,
457 writer: CellWriter<'b>,
458 ) -> Result<WrittenCellProof<'b>, SerializationError> {
459 serialize_mapping(
460 std::any::type_name::<Self>(),
461 self.len(),
462 self.iter(),
463 typ,
464 writer,
465 )
466 }
467}
468impl<T: SerializeValue> SerializeValue for Vec<T> {
469 fn serialize<'b>(
470 &self,
471 typ: &ColumnType,
472 writer: CellWriter<'b>,
473 ) -> Result<WrittenCellProof<'b>, SerializationError> {
474 serialize_sequence(
475 std::any::type_name::<Self>(),
476 self.len(),
477 self.iter(),
478 typ,
479 writer,
480 )
481 }
482}
483impl<'a, T: SerializeValue + 'a> SerializeValue for &'a [T] {
484 fn serialize<'b>(
485 &self,
486 typ: &ColumnType,
487 writer: CellWriter<'b>,
488 ) -> Result<WrittenCellProof<'b>, SerializationError> {
489 serialize_sequence(
490 std::any::type_name::<Self>(),
491 self.len(),
492 self.iter(),
493 typ,
494 writer,
495 )
496 }
497}
498impl SerializeValue for CqlValue {
499 fn serialize<'b>(
500 &self,
501 typ: &ColumnType,
502 writer: CellWriter<'b>,
503 ) -> Result<WrittenCellProof<'b>, SerializationError> {
504 serialize_cql_value(self, typ, writer).map_err(fix_cql_value_name_in_err)
505 }
506}
507
508fn serialize_cql_value<'b>(
509 value: &CqlValue,
510 typ: &ColumnType,
511 writer: CellWriter<'b>,
512) -> Result<WrittenCellProof<'b>, SerializationError> {
513 match value {
514 CqlValue::Ascii(a) => <_ as SerializeValue>::serialize(&a, typ, writer),
515 CqlValue::Boolean(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
516 CqlValue::Blob(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
517 CqlValue::Counter(c) => <_ as SerializeValue>::serialize(&c, typ, writer),
518 CqlValue::Decimal(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
519 CqlValue::Date(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
520 CqlValue::Double(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
521 CqlValue::Duration(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
522 CqlValue::Empty => {
523 if !typ.supports_special_empty_value() {
524 return Err(mk_typck_err::<CqlValue>(
525 typ,
526 BuiltinTypeCheckErrorKind::NotEmptyable,
527 ));
528 }
529 Ok(writer.set_value(&[]).unwrap())
530 }
531 CqlValue::Float(f) => <_ as SerializeValue>::serialize(&f, typ, writer),
532 CqlValue::Int(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
533 CqlValue::BigInt(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
534 CqlValue::Text(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
535 CqlValue::Timestamp(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
536 CqlValue::Inet(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
537 CqlValue::List(l) => <_ as SerializeValue>::serialize(&l, typ, writer),
538 CqlValue::Map(m) => serialize_mapping(
539 std::any::type_name::<CqlValue>(),
540 m.len(),
541 m.iter().map(|p| (&p.0, &p.1)),
542 typ,
543 writer,
544 ),
545 CqlValue::Set(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
546 CqlValue::UserDefinedType {
547 keyspace,
548 name: type_name,
549 fields,
550 } => serialize_udt(typ, keyspace, type_name, fields, writer),
551 CqlValue::SmallInt(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
552 CqlValue::TinyInt(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
553 CqlValue::Time(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
554 CqlValue::Timeuuid(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
555 CqlValue::Tuple(t) => {
556 let fields = match typ {
559 ColumnType::Tuple(fields) => {
560 if fields.len() < t.len() {
561 return Err(mk_typck_err::<CqlValue>(
562 typ,
563 TupleTypeCheckErrorKind::WrongElementCount {
564 rust_type_el_count: t.len(),
565 cql_type_el_count: fields.len(),
566 },
567 ));
568 }
569 fields
570 }
571 _ => {
572 return Err(mk_typck_err::<CqlValue>(
573 typ,
574 TupleTypeCheckErrorKind::NotTuple,
575 ))
576 }
577 };
578 serialize_tuple_like(typ, fields.iter(), t.iter(), writer)
579 }
580 CqlValue::Uuid(u) => <_ as SerializeValue>::serialize(&u, typ, writer),
581 CqlValue::Varint(v) => <_ as SerializeValue>::serialize(&v, typ, writer),
582 }
583}
584
585fn fix_cql_value_name_in_err(mut err: SerializationError) -> SerializationError {
586 let rust_name = std::any::type_name::<CqlValue>();
592
593 match Arc::get_mut(&mut err.0) {
594 Some(err_mut) => {
595 if let Some(err) = err_mut.downcast_mut::<BuiltinTypeCheckError>() {
596 err.rust_name = rust_name;
597 } else if let Some(err) = err_mut.downcast_mut::<BuiltinSerializationError>() {
598 err.rust_name = rust_name;
599 }
600 }
601 None => {
602 if let Some(err) = err.0.downcast_ref::<BuiltinTypeCheckError>() {
606 if err.rust_name != rust_name {
607 return SerializationError::new(BuiltinTypeCheckError {
608 rust_name,
609 ..err.clone()
610 });
611 }
612 }
613 if let Some(err) = err.0.downcast_ref::<BuiltinSerializationError>() {
614 if err.rust_name != rust_name {
615 return SerializationError::new(BuiltinSerializationError {
616 rust_name,
617 ..err.clone()
618 });
619 }
620 }
621 }
622 };
623
624 err
625}
626
627fn serialize_udt<'b>(
628 typ: &ColumnType,
629 keyspace: &str,
630 type_name: &str,
631 values: &[(String, Option<CqlValue>)],
632 writer: CellWriter<'b>,
633) -> Result<WrittenCellProof<'b>, SerializationError> {
634 let (dst_type_name, dst_keyspace, field_types) = match typ {
635 ColumnType::UserDefinedType {
636 definition: udt, ..
637 } => (&udt.name, &udt.keyspace, &udt.field_types),
638 _ => return Err(mk_typck_err::<CqlValue>(typ, UdtTypeCheckErrorKind::NotUdt)),
639 };
640
641 if keyspace != dst_keyspace || type_name != dst_type_name {
642 return Err(mk_typck_err::<CqlValue>(
643 typ,
644 UdtTypeCheckErrorKind::NameMismatch {
645 keyspace: dst_keyspace.clone().into_owned(),
646 type_name: dst_type_name.clone().into_owned(),
647 },
648 ));
649 }
650
651 let mut indexed_fields: HashMap<_, _> = values.iter().map(|(k, v)| (k.as_str(), v)).collect();
654
655 let mut builder = writer.into_value_builder();
656 for (fname, ftyp) in field_types {
657 let fvalue = indexed_fields
660 .remove(fname.deref())
661 .and_then(|x| x.as_ref());
662
663 let writer = builder.make_sub_writer();
664 match fvalue {
665 None => writer.set_null(),
666 Some(v) => serialize_cql_value(v, ftyp, writer).map_err(|err| {
667 let err = fix_cql_value_name_in_err(err);
668 mk_ser_err::<CqlValue>(
669 typ,
670 UdtSerializationErrorKind::FieldSerializationFailed {
671 field_name: fname.clone().into_owned(),
672 err,
673 },
674 )
675 })?,
676 };
677 }
678
679 if !indexed_fields.is_empty() {
681 let fname = indexed_fields.keys().min().unwrap();
684 return Err(mk_typck_err::<CqlValue>(
685 typ,
686 UdtTypeCheckErrorKind::NoSuchFieldInUdt {
687 field_name: fname.to_string(),
688 },
689 ));
690 }
691
692 builder
693 .finish()
694 .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
695}
696
697fn serialize_tuple_like<'t, 'b>(
698 typ: &ColumnType,
699 field_types: impl Iterator<Item = &'t ColumnType<'t>>,
700 field_values: impl Iterator<Item = &'t Option<CqlValue>>,
701 writer: CellWriter<'b>,
702) -> Result<WrittenCellProof<'b>, SerializationError> {
703 let mut builder = writer.into_value_builder();
704
705 for (index, (el, el_typ)) in field_values.zip(field_types).enumerate() {
706 let sub = builder.make_sub_writer();
707 match el {
708 None => sub.set_null(),
709 Some(el) => serialize_cql_value(el, el_typ, sub).map_err(|err| {
710 let err = fix_cql_value_name_in_err(err);
711 mk_ser_err::<CqlValue>(
712 typ,
713 TupleSerializationErrorKind::ElementSerializationFailed { index, err },
714 )
715 })?,
716 };
717 }
718
719 builder
720 .finish()
721 .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
722}
723
724macro_rules! impl_tuple {
725 (
726 $($typs:ident),*;
727 $($fidents:ident),*;
728 $($tidents:ident),*;
729 $length:expr
730 ) => {
731 impl<$($typs: SerializeValue),*> SerializeValue for ($($typs,)*) {
732 fn serialize<'b>(
733 &self,
734 typ: &ColumnType,
735 writer: CellWriter<'b>,
736 ) -> Result<WrittenCellProof<'b>, SerializationError> {
737 let ($($tidents,)*) = match typ {
738 ColumnType::Tuple(typs) => match typs.as_slice() {
739 [$($tidents),*] => ($($tidents,)*),
740 _ => return Err(mk_typck_err::<Self>(
741 typ,
742 TupleTypeCheckErrorKind::WrongElementCount {
743 rust_type_el_count: $length,
744 cql_type_el_count: typs.len(),
745 }
746 ))
747 }
748 _ => return Err(mk_typck_err::<Self>(
749 typ,
750 TupleTypeCheckErrorKind::NotTuple,
751 ))
752 };
753 let ($($fidents,)*) = self;
754 let mut builder = writer.into_value_builder();
755 let index = 0;
756 $(
757 <$typs as SerializeValue>::serialize($fidents, $tidents, builder.make_sub_writer())
758 .map_err(|err| mk_ser_err::<Self>(
759 typ,
760 TupleSerializationErrorKind::ElementSerializationFailed {
761 index,
762 err,
763 }
764 ))?;
765 let index = index + 1;
766 )*
767 let _ = index;
768 builder
769 .finish()
770 .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))
771 }
772 }
773 };
774}
775
776macro_rules! impl_tuples {
777 (;;;$length:expr) => {};
778 (
779 $typ:ident$(, $($typs:ident),*)?;
780 $fident:ident$(, $($fidents:ident),*)?;
781 $tident:ident$(, $($tidents:ident),*)?;
782 $length:expr
783 ) => {
784 impl_tuples!(
785 $($($typs),*)?;
786 $($($fidents),*)?;
787 $($($tidents),*)?;
788 $length - 1
789 );
790 impl_tuple!(
791 $typ$(, $($typs),*)?;
792 $fident$(, $($fidents),*)?;
793 $tident$(, $($tidents),*)?;
794 $length
795 );
796 };
797}
798
799impl_tuples!(
800 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15;
801 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15;
802 t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15;
803 16
804);
805
806fn serialize_sequence<'t, 'b, T: SerializeValue + 't>(
807 rust_name: &'static str,
808 len: usize,
809 iter: impl Iterator<Item = &'t T>,
810 typ: &ColumnType,
811 writer: CellWriter<'b>,
812) -> Result<WrittenCellProof<'b>, SerializationError> {
813 let elt = match typ {
814 ColumnType::Collection {
815 frozen: false,
816 typ: CollectionType::List(elt),
817 }
818 | ColumnType::Collection {
819 frozen: false,
820 typ: CollectionType::Set(elt),
821 } => elt,
822 _ => {
823 return Err(mk_typck_err_named(
824 rust_name,
825 typ,
826 SetOrListTypeCheckErrorKind::NotSetOrList,
827 ));
828 }
829 };
830
831 let mut builder = writer.into_value_builder();
832
833 let element_count: i32 = len.try_into().map_err(|_| {
834 mk_ser_err_named(
835 rust_name,
836 typ,
837 SetOrListSerializationErrorKind::TooManyElements,
838 )
839 })?;
840 builder.append_bytes(&element_count.to_be_bytes());
841
842 for el in iter {
843 T::serialize(el, elt, builder.make_sub_writer()).map_err(|err| {
844 mk_ser_err_named(
845 rust_name,
846 typ,
847 SetOrListSerializationErrorKind::ElementSerializationFailed(err),
848 )
849 })?;
850 }
851
852 builder
853 .finish()
854 .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
855}
856
857fn serialize_mapping<'t, 'b, K: SerializeValue + 't, V: SerializeValue + 't>(
858 rust_name: &'static str,
859 len: usize,
860 iter: impl Iterator<Item = (&'t K, &'t V)>,
861 typ: &ColumnType,
862 writer: CellWriter<'b>,
863) -> Result<WrittenCellProof<'b>, SerializationError> {
864 let (ktyp, vtyp) = match typ {
865 ColumnType::Collection {
866 frozen: false,
867 typ: CollectionType::Map(k, v),
868 } => (k, v),
869 _ => {
870 return Err(mk_typck_err_named(
871 rust_name,
872 typ,
873 MapTypeCheckErrorKind::NotMap,
874 ));
875 }
876 };
877
878 let mut builder = writer.into_value_builder();
879
880 let element_count: i32 = len.try_into().map_err(|_| {
881 mk_ser_err_named(rust_name, typ, MapSerializationErrorKind::TooManyElements)
882 })?;
883 builder.append_bytes(&element_count.to_be_bytes());
884
885 for (k, v) in iter {
886 K::serialize(k, ktyp, builder.make_sub_writer()).map_err(|err| {
887 mk_ser_err_named(
888 rust_name,
889 typ,
890 MapSerializationErrorKind::KeySerializationFailed(err),
891 )
892 })?;
893 V::serialize(v, vtyp, builder.make_sub_writer()).map_err(|err| {
894 mk_ser_err_named(
895 rust_name,
896 typ,
897 MapSerializationErrorKind::ValueSerializationFailed(err),
898 )
899 })?;
900 }
901
902 builder
903 .finish()
904 .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
905}
906
907#[derive(Debug, Error, Clone)]
909#[error("Failed to type check Rust type {rust_name} against CQL type {got:?}: {kind}")]
910pub struct BuiltinTypeCheckError {
911 pub rust_name: &'static str,
913
914 pub got: ColumnType<'static>,
916
917 pub kind: BuiltinTypeCheckErrorKind,
919}
920
921fn mk_typck_err<T>(
922 got: &ColumnType,
923 kind: impl Into<BuiltinTypeCheckErrorKind>,
924) -> SerializationError {
925 mk_typck_err_named(std::any::type_name::<T>(), got, kind)
926}
927
928fn mk_typck_err_named(
929 name: &'static str,
930 got: &ColumnType,
931 kind: impl Into<BuiltinTypeCheckErrorKind>,
932) -> SerializationError {
933 SerializationError::new(BuiltinTypeCheckError {
934 rust_name: name,
935 got: got.clone().into_owned(),
936 kind: kind.into(),
937 })
938}
939
940#[derive(Debug, Error, Clone)]
942#[error("Failed to serialize Rust type {rust_name} into CQL type {got:?}: {kind}")]
943pub struct BuiltinSerializationError {
944 pub rust_name: &'static str,
946
947 pub got: ColumnType<'static>,
949
950 pub kind: BuiltinSerializationErrorKind,
952}
953
954pub(crate) fn mk_ser_err<T>(
955 got: &ColumnType,
956 kind: impl Into<BuiltinSerializationErrorKind>,
957) -> SerializationError {
958 mk_ser_err_named(std::any::type_name::<T>(), got, kind)
959}
960
961fn mk_ser_err_named(
962 name: &'static str,
963 got: &ColumnType,
964 kind: impl Into<BuiltinSerializationErrorKind>,
965) -> SerializationError {
966 SerializationError::new(BuiltinSerializationError {
967 rust_name: name,
968 got: got.clone().into_owned(),
969 kind: kind.into(),
970 })
971}
972
973#[derive(Debug, Clone)]
975#[non_exhaustive]
976pub enum BuiltinTypeCheckErrorKind {
977 MismatchedType {
979 expected: &'static [ColumnType<'static>],
981 },
982
983 NotEmptyable,
985
986 SetOrListError(SetOrListTypeCheckErrorKind),
988
989 MapError(MapTypeCheckErrorKind),
991
992 TupleError(TupleTypeCheckErrorKind),
994
995 UdtError(UdtTypeCheckErrorKind),
997}
998
999impl From<SetOrListTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1000 fn from(value: SetOrListTypeCheckErrorKind) -> Self {
1001 BuiltinTypeCheckErrorKind::SetOrListError(value)
1002 }
1003}
1004
1005impl From<MapTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1006 fn from(value: MapTypeCheckErrorKind) -> Self {
1007 BuiltinTypeCheckErrorKind::MapError(value)
1008 }
1009}
1010
1011impl From<TupleTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1012 fn from(value: TupleTypeCheckErrorKind) -> Self {
1013 BuiltinTypeCheckErrorKind::TupleError(value)
1014 }
1015}
1016
1017impl From<UdtTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1018 fn from(value: UdtTypeCheckErrorKind) -> Self {
1019 BuiltinTypeCheckErrorKind::UdtError(value)
1020 }
1021}
1022
1023impl Display for BuiltinTypeCheckErrorKind {
1024 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1025 match self {
1026 BuiltinTypeCheckErrorKind::MismatchedType { expected } => {
1027 write!(f, "expected one of the CQL types: {expected:?}")
1028 }
1029 BuiltinTypeCheckErrorKind::NotEmptyable => {
1030 f.write_str("the separate empty representation is not valid for this type")
1031 }
1032 BuiltinTypeCheckErrorKind::SetOrListError(err) => err.fmt(f),
1033 BuiltinTypeCheckErrorKind::MapError(err) => err.fmt(f),
1034 BuiltinTypeCheckErrorKind::TupleError(err) => err.fmt(f),
1035 BuiltinTypeCheckErrorKind::UdtError(err) => err.fmt(f),
1036 }
1037 }
1038}
1039
1040#[derive(Debug, Clone)]
1042#[non_exhaustive]
1043pub enum BuiltinSerializationErrorKind {
1044 SizeOverflow,
1047
1048 ValueOverflow,
1050
1051 SetOrListError(SetOrListSerializationErrorKind),
1053
1054 MapError(MapSerializationErrorKind),
1056
1057 TupleError(TupleSerializationErrorKind),
1059
1060 UdtError(UdtSerializationErrorKind),
1062}
1063
1064impl From<SetOrListSerializationErrorKind> for BuiltinSerializationErrorKind {
1065 fn from(value: SetOrListSerializationErrorKind) -> Self {
1066 BuiltinSerializationErrorKind::SetOrListError(value)
1067 }
1068}
1069
1070impl From<MapSerializationErrorKind> for BuiltinSerializationErrorKind {
1071 fn from(value: MapSerializationErrorKind) -> Self {
1072 BuiltinSerializationErrorKind::MapError(value)
1073 }
1074}
1075
1076impl From<TupleSerializationErrorKind> for BuiltinSerializationErrorKind {
1077 fn from(value: TupleSerializationErrorKind) -> Self {
1078 BuiltinSerializationErrorKind::TupleError(value)
1079 }
1080}
1081
1082impl From<UdtSerializationErrorKind> for BuiltinSerializationErrorKind {
1083 fn from(value: UdtSerializationErrorKind) -> Self {
1084 BuiltinSerializationErrorKind::UdtError(value)
1085 }
1086}
1087
1088impl Display for BuiltinSerializationErrorKind {
1089 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1090 match self {
1091 BuiltinSerializationErrorKind::SizeOverflow => {
1092 f.write_str("the Rust value is too big to be serialized in the CQL protocol format")
1093 }
1094 BuiltinSerializationErrorKind::ValueOverflow => {
1095 f.write_str("the Rust value is out of range supported by the CQL type")
1096 }
1097 BuiltinSerializationErrorKind::SetOrListError(err) => err.fmt(f),
1098 BuiltinSerializationErrorKind::MapError(err) => err.fmt(f),
1099 BuiltinSerializationErrorKind::TupleError(err) => err.fmt(f),
1100 BuiltinSerializationErrorKind::UdtError(err) => err.fmt(f),
1101 }
1102 }
1103}
1104
1105#[derive(Debug, Clone)]
1107#[non_exhaustive]
1108pub enum MapTypeCheckErrorKind {
1109 NotMap,
1111}
1112
1113impl Display for MapTypeCheckErrorKind {
1114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1115 match self {
1116 MapTypeCheckErrorKind::NotMap => f.write_str(
1117 "the CQL type the Rust type was attempted to be type checked against was not a map",
1118 ),
1119 }
1120 }
1121}
1122
1123#[derive(Debug, Clone)]
1125#[non_exhaustive]
1126pub enum MapSerializationErrorKind {
1127 TooManyElements,
1129
1130 KeySerializationFailed(SerializationError),
1132
1133 ValueSerializationFailed(SerializationError),
1135}
1136
1137impl Display for MapSerializationErrorKind {
1138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1139 match self {
1140 MapSerializationErrorKind::TooManyElements => {
1141 f.write_str("the map contains too many elements to fit in CQL representation")
1142 }
1143 MapSerializationErrorKind::KeySerializationFailed(err) => {
1144 write!(f, "failed to serialize one of the keys: {}", err)
1145 }
1146 MapSerializationErrorKind::ValueSerializationFailed(err) => {
1147 write!(f, "failed to serialize one of the values: {}", err)
1148 }
1149 }
1150 }
1151}
1152
1153#[derive(Debug, Clone)]
1155#[non_exhaustive]
1156pub enum SetOrListTypeCheckErrorKind {
1157 NotSetOrList,
1159}
1160
1161impl Display for SetOrListTypeCheckErrorKind {
1162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1163 match self {
1164 SetOrListTypeCheckErrorKind::NotSetOrList => {
1165 f.write_str("the CQL type the Rust type was attempted to be type checked against was neither a set or a list")
1166 }
1167 }
1168 }
1169}
1170
1171#[derive(Debug, Clone)]
1173#[non_exhaustive]
1174pub enum SetOrListSerializationErrorKind {
1175 TooManyElements,
1177
1178 ElementSerializationFailed(SerializationError),
1180}
1181
1182impl Display for SetOrListSerializationErrorKind {
1183 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1184 match self {
1185 SetOrListSerializationErrorKind::TooManyElements => f.write_str(
1186 "the collection contains too many elements to fit in CQL representation",
1187 ),
1188 SetOrListSerializationErrorKind::ElementSerializationFailed(err) => {
1189 write!(f, "failed to serialize one of the elements: {err}")
1190 }
1191 }
1192 }
1193}
1194
1195#[derive(Debug, Clone)]
1197#[non_exhaustive]
1198pub enum TupleTypeCheckErrorKind {
1199 NotTuple,
1201
1202 WrongElementCount {
1208 rust_type_el_count: usize,
1210
1211 cql_type_el_count: usize,
1213 },
1214}
1215
1216impl Display for TupleTypeCheckErrorKind {
1217 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1218 match self {
1219 TupleTypeCheckErrorKind::NotTuple => f.write_str(
1220 "the CQL type the Rust type was attempted to be type checked against is not a tuple"
1221 ),
1222 TupleTypeCheckErrorKind::WrongElementCount { rust_type_el_count, cql_type_el_count } => write!(
1223 f,
1224 "wrong tuple element count: CQL type has {cql_type_el_count}, the Rust tuple has {rust_type_el_count}"
1225 ),
1226 }
1227 }
1228}
1229
1230#[derive(Debug, Clone)]
1232#[non_exhaustive]
1233pub enum TupleSerializationErrorKind {
1234 ElementSerializationFailed {
1236 index: usize,
1238
1239 err: SerializationError,
1241 },
1242}
1243
1244impl Display for TupleSerializationErrorKind {
1245 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1246 match self {
1247 TupleSerializationErrorKind::ElementSerializationFailed { index, err } => {
1248 write!(f, "element no. {index} failed to serialize: {err}")
1249 }
1250 }
1251 }
1252}
1253
1254#[derive(Debug, Clone)]
1256#[non_exhaustive]
1257pub enum UdtTypeCheckErrorKind {
1258 NotUdt,
1260
1261 NameMismatch {
1263 keyspace: String,
1265
1266 type_name: String,
1268 },
1269
1270 ValueMissingForUdtField {
1272 field_name: String,
1274 },
1275
1276 NoSuchFieldInUdt {
1278 field_name: String,
1280 },
1281
1282 FieldNameMismatch {
1284 rust_field_name: String,
1286
1287 db_field_name: String,
1289 },
1290}
1291
1292impl Display for UdtTypeCheckErrorKind {
1293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1294 match self {
1295 UdtTypeCheckErrorKind::NotUdt => f.write_str("the CQL type the Rust type was attempted to be type checked against is not a UDT"),
1296 UdtTypeCheckErrorKind::NameMismatch {
1297 keyspace,
1298 type_name,
1299 } => write!(
1300 f,
1301 "the Rust UDT name does not match the actual CQL UDT name ({keyspace}.{type_name})"
1302 ),
1303 UdtTypeCheckErrorKind::ValueMissingForUdtField { field_name } => {
1304 write!(f, "the field {field_name} is missing in the Rust data but is required by the CQL UDT type")
1305 }
1306 UdtTypeCheckErrorKind::NoSuchFieldInUdt { field_name } => write!(
1307 f,
1308 "the field {field_name} that is present in the Rust data is not present in the CQL type"
1309 ),
1310 UdtTypeCheckErrorKind::FieldNameMismatch { rust_field_name, db_field_name } => write!(
1311 f,
1312 "expected field with name {db_field_name} at given position, but the Rust field name is {rust_field_name}"
1313 ),
1314 }
1315 }
1316}
1317
1318#[derive(Debug, Clone)]
1320#[non_exhaustive]
1321pub enum UdtSerializationErrorKind {
1322 FieldSerializationFailed {
1324 field_name: String,
1326
1327 err: SerializationError,
1329 },
1330}
1331
1332impl Display for UdtSerializationErrorKind {
1333 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1334 match self {
1335 UdtSerializationErrorKind::FieldSerializationFailed { field_name, err } => {
1336 write!(f, "field {field_name} failed to serialize: {err}")
1337 }
1338 }
1339 }
1340}
1341
1342mod doctests {
1343 fn _test_udt_bad_attributes_skip_name_check_requires_enforce_order() {}
1350
1351 fn _test_udt_bad_attributes_skip_name_check_conflicts_with_rename() {}
1361
1362 fn _test_udt_bad_attributes_rename_collision_with_field() {}
1373
1374 fn _test_udt_bad_attributes_rename_collision_with_another_rename() {}
1386
1387 fn _test_udt_bad_attributes_name_skip_name_checks_limitations_on_allow_missing() {}
1399
1400 fn _test_udt_good_attributes_name_skip_name_checks_limitations_on_allow_missing() {}
1413
1414 fn _test_udt_unordered_flavour_no_limitations_on_allow_missing() {}
1425
1426 fn _test_udt_default_when_null_is_accepted() {}
1437}
1438
1439#[cfg(test)]
1440#[path = "value_tests.rs"]
1441pub(crate) mod tests;