Skip to main content

scylla_cql/serialize/
value.rs

1//! Contains the [`SerializeValue`] trait and its implementations.
2
3// Note: When editing above doc-comment edit the corresponding comment on
4// re-export module in scylla crate too.
5
6use std::borrow::Cow;
7use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
8use std::fmt::Display;
9use std::hash::BuildHasher;
10use std::net::IpAddr;
11use std::ops::Deref as _;
12use std::sync::Arc;
13
14use bytes::Bytes;
15use thiserror::Error;
16use uuid::Uuid;
17
18use crate::frame::response::result::{CollectionType, ColumnType, NativeType};
19use crate::frame::types::{unsigned_vint_encode, vint_encode};
20use crate::value::{
21    Counter, CqlDate, CqlDecimal, CqlDecimalBorrowed, CqlDuration, CqlTime, CqlTimestamp,
22    CqlTimeuuid, CqlValue, CqlVarint, CqlVarintBorrowed, Emptiable, MaybeEmpty, MaybeUnset, Unset,
23};
24
25#[cfg(feature = "chrono-04")]
26use crate::value::ValueOverflow;
27
28use super::writers::WrittenCellProof;
29use super::{CellValueBuilder, CellWriter, SerializationError};
30
31/// A type that can be serialized and sent along with a CQL statement.
32///
33/// This is a low-level trait that is exposed to the specifics to the CQL
34/// protocol and usually does not have to be implemented directly. See the
35/// chapter on "Query Values" in the driver docs for information about how
36/// this trait is supposed to be used.
37pub trait SerializeValue {
38    /// Serializes the value to given CQL type.
39    ///
40    /// The value should produce a `[value]`, according to the [CQL protocol
41    /// specification](https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec),
42    /// containing the serialized value. See section 6 of the document on how
43    /// the contents of the `[value]` should look like.
44    ///
45    /// The value produced should match the type provided by `typ`. If the
46    /// value cannot be serialized to that type, an error should be returned.
47    ///
48    /// The [`CellWriter`] provided to the method ensures that the value produced
49    /// will be properly framed (i.e. incorrectly written value should not
50    /// cause the rest of the request to be misinterpreted), but otherwise
51    /// the implementor of the trait is responsible for producing the value
52    /// in a correct format.
53    fn serialize<'b>(
54        &self,
55        typ: &ColumnType,
56        writer: CellWriter<'b>,
57    ) -> Result<WrittenCellProof<'b>, SerializationError>;
58}
59
60macro_rules! exact_type_check {
61    ($typ:ident, $($cql:tt),*) => {
62        match $typ {
63            $(ColumnType::Native(NativeType::$cql))|* => {},
64            _ => return Err(mk_typck_err::<Self>(
65                $typ,
66                BuiltinTypeCheckErrorKind::MismatchedType {
67                    expected: &[$(ColumnType::Native(NativeType::$cql)),*],
68                }
69            ))
70        }
71    };
72}
73
74macro_rules! impl_serialize_via_writer {
75    (|$me:ident, $writer:ident| $e:expr) => {
76        impl_serialize_via_writer!(|$me, _typ, $writer| $e);
77    };
78    (|$me:ident, $typ:ident, $writer:ident| $e:expr) => {
79        fn serialize<'b>(
80            &self,
81            typ: &ColumnType,
82            writer: CellWriter<'b>,
83        ) -> Result<WrittenCellProof<'b>, SerializationError> {
84            let $writer = writer;
85            let $typ = typ;
86            let $me = self;
87            let proof = $e;
88            Ok(proof)
89        }
90    };
91}
92
93impl SerializeValue for i8 {
94    impl_serialize_via_writer!(|me, typ, writer| {
95        exact_type_check!(typ, TinyInt);
96        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
97    });
98}
99impl SerializeValue for i16 {
100    impl_serialize_via_writer!(|me, typ, writer| {
101        exact_type_check!(typ, SmallInt);
102        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
103    });
104}
105impl SerializeValue for i32 {
106    impl_serialize_via_writer!(|me, typ, writer| {
107        exact_type_check!(typ, Int);
108        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
109    });
110}
111impl SerializeValue for i64 {
112    impl_serialize_via_writer!(|me, typ, writer| {
113        exact_type_check!(typ, BigInt);
114        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
115    });
116}
117impl SerializeValue for CqlDecimal {
118    impl_serialize_via_writer!(|me, typ, writer| {
119        exact_type_check!(typ, Decimal);
120        let mut builder = writer.into_value_builder();
121        let (bytes, scale) = me.as_signed_be_bytes_slice_and_exponent();
122        builder.append_bytes(&scale.to_be_bytes());
123        builder.append_bytes(bytes);
124        builder
125            .finish()
126            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
127    });
128}
129impl SerializeValue for CqlDecimalBorrowed<'_> {
130    impl_serialize_via_writer!(|me, typ, writer| {
131        exact_type_check!(typ, Decimal);
132        let mut builder = writer.into_value_builder();
133        let (bytes, scale) = me.as_signed_be_bytes_slice_and_exponent();
134        builder.append_bytes(&scale.to_be_bytes());
135        builder.append_bytes(bytes);
136        builder
137            .finish()
138            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
139    });
140}
141#[cfg(feature = "bigdecimal-04")]
142impl SerializeValue for bigdecimal_04::BigDecimal {
143    impl_serialize_via_writer!(|me, typ, writer| {
144        exact_type_check!(typ, Decimal);
145        let mut builder = writer.into_value_builder();
146        let (value, scale) = me.as_bigint_and_exponent();
147        let scale: i32 = scale
148            .try_into()
149            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::ValueOverflow))?;
150        builder.append_bytes(&scale.to_be_bytes());
151        builder.append_bytes(&value.to_signed_bytes_be());
152        builder
153            .finish()
154            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
155    });
156}
157impl SerializeValue for CqlDate {
158    impl_serialize_via_writer!(|me, typ, writer| {
159        exact_type_check!(typ, Date);
160        writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
161    });
162}
163impl SerializeValue for CqlTimestamp {
164    impl_serialize_via_writer!(|me, typ, writer| {
165        exact_type_check!(typ, Timestamp);
166        writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
167    });
168}
169impl SerializeValue for CqlTime {
170    impl_serialize_via_writer!(|me, typ, writer| {
171        exact_type_check!(typ, Time);
172        writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
173    });
174}
175#[cfg(feature = "chrono-04")]
176impl SerializeValue for chrono_04::NaiveDate {
177    impl_serialize_via_writer!(|me, typ, writer| {
178        exact_type_check!(typ, Date);
179        <CqlDate as SerializeValue>::serialize(&(*me).into(), typ, writer)?
180    });
181}
182#[cfg(feature = "chrono-04")]
183impl SerializeValue for chrono_04::DateTime<chrono_04::Utc> {
184    impl_serialize_via_writer!(|me, typ, writer| {
185        exact_type_check!(typ, Timestamp);
186        <CqlTimestamp as SerializeValue>::serialize(&(*me).into(), typ, writer)?
187    });
188}
189#[cfg(feature = "chrono-04")]
190impl SerializeValue for chrono_04::NaiveTime {
191    impl_serialize_via_writer!(|me, typ, writer| {
192        exact_type_check!(typ, Time);
193        let cql_time = CqlTime::try_from(*me).map_err(|_: ValueOverflow| {
194            mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::ValueOverflow)
195        })?;
196        <CqlTime as SerializeValue>::serialize(&cql_time, typ, writer)?
197    });
198}
199#[cfg(feature = "time-03")]
200impl SerializeValue for time_03::Date {
201    impl_serialize_via_writer!(|me, typ, writer| {
202        exact_type_check!(typ, Date);
203        <CqlDate as SerializeValue>::serialize(&(*me).into(), typ, writer)?
204    });
205}
206#[cfg(feature = "time-03")]
207impl SerializeValue for time_03::OffsetDateTime {
208    impl_serialize_via_writer!(|me, typ, writer| {
209        exact_type_check!(typ, Timestamp);
210        <CqlTimestamp as SerializeValue>::serialize(&(*me).into(), typ, writer)?
211    });
212}
213#[cfg(feature = "time-03")]
214impl SerializeValue for time_03::Time {
215    impl_serialize_via_writer!(|me, typ, writer| {
216        exact_type_check!(typ, Time);
217        <CqlTime as SerializeValue>::serialize(&(*me).into(), typ, writer)?
218    });
219}
220#[cfg(feature = "secrecy-08")]
221impl<V: SerializeValue + secrecy_08::Zeroize> SerializeValue for secrecy_08::Secret<V> {
222    fn serialize<'b>(
223        &self,
224        typ: &ColumnType,
225        writer: CellWriter<'b>,
226    ) -> Result<WrittenCellProof<'b>, SerializationError> {
227        use secrecy_08::ExposeSecret;
228        V::serialize(self.expose_secret(), typ, writer).map_err(fix_rust_name_in_err::<Self>)
229    }
230}
231#[cfg(feature = "secrecy-10")]
232impl<V: SerializeValue + secrecy_10::zeroize::Zeroize + ?Sized> SerializeValue
233    for secrecy_10::SecretBox<V>
234{
235    fn serialize<'b>(
236        &self,
237        typ: &ColumnType,
238        writer: CellWriter<'b>,
239    ) -> Result<WrittenCellProof<'b>, SerializationError> {
240        use secrecy_10::ExposeSecret;
241        V::serialize(self.expose_secret(), typ, writer).map_err(fix_rust_name_in_err::<Self>)
242    }
243}
244impl SerializeValue for bool {
245    impl_serialize_via_writer!(|me, typ, writer| {
246        exact_type_check!(typ, Boolean);
247        writer.set_value(&[*me as u8]).unwrap()
248    });
249}
250impl SerializeValue for f32 {
251    impl_serialize_via_writer!(|me, typ, writer| {
252        exact_type_check!(typ, Float);
253        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
254    });
255}
256impl SerializeValue for f64 {
257    impl_serialize_via_writer!(|me, typ, writer| {
258        exact_type_check!(typ, Double);
259        writer.set_value(me.to_be_bytes().as_slice()).unwrap()
260    });
261}
262impl SerializeValue for Uuid {
263    impl_serialize_via_writer!(|me, typ, writer| {
264        exact_type_check!(typ, Uuid);
265        writer.set_value(me.as_bytes().as_ref()).unwrap()
266    });
267}
268impl SerializeValue for CqlTimeuuid {
269    impl_serialize_via_writer!(|me, typ, writer| {
270        exact_type_check!(typ, Timeuuid);
271        writer.set_value(me.as_bytes().as_ref()).unwrap()
272    });
273}
274impl SerializeValue for CqlVarint {
275    impl_serialize_via_writer!(|me, typ, writer| {
276        exact_type_check!(typ, Varint);
277        writer
278            .set_value(me.as_signed_bytes_be_slice())
279            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
280    });
281}
282impl SerializeValue for CqlVarintBorrowed<'_> {
283    impl_serialize_via_writer!(|me, typ, writer| {
284        exact_type_check!(typ, Varint);
285        writer
286            .set_value(me.as_signed_bytes_be_slice())
287            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
288    });
289}
290#[cfg(feature = "num-bigint-03")]
291impl SerializeValue for num_bigint_03::BigInt {
292    impl_serialize_via_writer!(|me, typ, writer| {
293        exact_type_check!(typ, Varint);
294        // TODO: The allocation here can be avoided and we can reimplement
295        // `to_signed_bytes_be` by using `to_u64_digits` and a bit of custom
296        // logic. Need better tests in order to do this.
297        writer
298            .set_value(me.to_signed_bytes_be().as_slice())
299            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
300    });
301}
302#[cfg(feature = "num-bigint-04")]
303impl SerializeValue for num_bigint_04::BigInt {
304    impl_serialize_via_writer!(|me, typ, writer| {
305        exact_type_check!(typ, Varint);
306        // TODO: See above comment for num-bigint-03.
307        writer
308            .set_value(me.to_signed_bytes_be().as_slice())
309            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
310    });
311}
312impl SerializeValue for str {
313    impl_serialize_via_writer!(|me, typ, writer| {
314        exact_type_check!(typ, Ascii, Text);
315        writer
316            .set_value(me.as_bytes())
317            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
318    });
319}
320impl SerializeValue for Vec<u8> {
321    impl_serialize_via_writer!(|me, typ, writer| {
322        exact_type_check!(typ, Blob);
323        writer
324            .set_value(me.as_ref())
325            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
326    });
327}
328impl SerializeValue for &[u8] {
329    impl_serialize_via_writer!(|me, typ, writer| {
330        exact_type_check!(typ, Blob);
331        writer
332            .set_value(me)
333            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
334    });
335}
336impl<const N: usize> SerializeValue for [u8; N] {
337    impl_serialize_via_writer!(|me, typ, writer| {
338        exact_type_check!(typ, Blob);
339        writer
340            .set_value(me.as_ref())
341            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
342    });
343}
344impl SerializeValue for Bytes {
345    impl_serialize_via_writer!(|me, typ, writer| {
346        exact_type_check!(typ, Blob);
347        writer
348            .set_value(me)
349            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
350    });
351}
352impl SerializeValue for IpAddr {
353    impl_serialize_via_writer!(|me, typ, writer| {
354        exact_type_check!(typ, Inet);
355        match me {
356            IpAddr::V4(ip) => writer.set_value(&ip.octets()).unwrap(),
357            IpAddr::V6(ip) => writer.set_value(&ip.octets()).unwrap(),
358        }
359    });
360}
361impl SerializeValue for String {
362    impl_serialize_via_writer!(|me, typ, writer| {
363        exact_type_check!(typ, Ascii, Text);
364        writer
365            .set_value(me.as_bytes())
366            .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))?
367    });
368}
369impl<T: SerializeValue> SerializeValue for Option<T> {
370    fn serialize<'b>(
371        &self,
372        typ: &ColumnType,
373        writer: CellWriter<'b>,
374    ) -> Result<WrittenCellProof<'b>, SerializationError> {
375        match self {
376            Some(v) => v
377                .serialize(typ, writer)
378                .map_err(fix_rust_name_in_err::<Self>),
379            None => Ok(writer.set_null()),
380        }
381    }
382}
383impl SerializeValue for Unset {
384    impl_serialize_via_writer!(|_me, writer| writer.set_unset());
385}
386impl SerializeValue for Counter {
387    impl_serialize_via_writer!(|me, typ, writer| {
388        exact_type_check!(typ, Counter);
389        writer.set_value(me.0.to_be_bytes().as_slice()).unwrap()
390    });
391}
392impl SerializeValue for CqlDuration {
393    impl_serialize_via_writer!(|me, typ, writer| {
394        exact_type_check!(typ, Duration);
395        // TODO: adjust vint_encode to use CellValueBuilder or something like that
396        let mut buf = Vec::with_capacity(27); // worst case size is 27
397        vint_encode(me.months as i64, &mut buf);
398        vint_encode(me.days as i64, &mut buf);
399        vint_encode(me.nanoseconds, &mut buf);
400        writer.set_value(buf.as_slice()).unwrap()
401    });
402}
403impl<V: SerializeValue> SerializeValue for MaybeUnset<V> {
404    fn serialize<'b>(
405        &self,
406        typ: &ColumnType,
407        writer: CellWriter<'b>,
408    ) -> Result<WrittenCellProof<'b>, SerializationError> {
409        match self {
410            MaybeUnset::Set(v) => v
411                .serialize(typ, writer)
412                .map_err(fix_rust_name_in_err::<Self>),
413            MaybeUnset::Unset => Ok(writer.set_unset()),
414        }
415    }
416}
417impl<T: SerializeValue + Emptiable> SerializeValue for MaybeEmpty<T> {
418    fn serialize<'b>(
419        &self,
420        typ: &ColumnType,
421        writer: CellWriter<'b>,
422    ) -> Result<WrittenCellProof<'b>, SerializationError> {
423        // Check that the type supports empty values
424        if !typ.supports_special_empty_value() {
425            return Err(mk_typck_err::<Self>(
426                typ,
427                BuiltinTypeCheckErrorKind::NotEmptyable,
428            ));
429        }
430
431        match self {
432            MaybeEmpty::Empty => Ok(writer.set_value(&[]).unwrap()),
433            MaybeEmpty::Value(v) => v
434                .serialize(typ, writer)
435                .map_err(fix_rust_name_in_err::<Self>),
436        }
437    }
438}
439impl<T: SerializeValue + ?Sized> SerializeValue for &T {
440    fn serialize<'b>(
441        &self,
442        typ: &ColumnType,
443        writer: CellWriter<'b>,
444    ) -> Result<WrittenCellProof<'b>, SerializationError> {
445        T::serialize(*self, typ, writer).map_err(fix_rust_name_in_err::<Self>)
446    }
447}
448impl<T: SerializeValue + ?Sized> SerializeValue for Box<T> {
449    fn serialize<'b>(
450        &self,
451        typ: &ColumnType,
452        writer: CellWriter<'b>,
453    ) -> Result<WrittenCellProof<'b>, SerializationError> {
454        T::serialize(&**self, typ, writer).map_err(fix_rust_name_in_err::<Self>)
455    }
456}
457impl<T: SerializeValue + ?Sized> SerializeValue for Arc<T> {
458    fn serialize<'b>(
459        &self,
460        typ: &ColumnType,
461        writer: CellWriter<'b>,
462    ) -> Result<WrittenCellProof<'b>, SerializationError> {
463        T::serialize(&**self, typ, writer).map_err(fix_rust_name_in_err::<Self>)
464    }
465}
466impl<T: SerializeValue + ?Sized + ToOwned> SerializeValue for Cow<'_, T> {
467    fn serialize<'b>(
468        &self,
469        typ: &ColumnType,
470        writer: CellWriter<'b>,
471    ) -> Result<WrittenCellProof<'b>, SerializationError> {
472        T::serialize(self.as_ref(), typ, writer).map_err(fix_rust_name_in_err::<Self>)
473    }
474}
475impl<V: SerializeValue, S: BuildHasher + Default> SerializeValue for HashSet<V, S> {
476    fn serialize<'b>(
477        &self,
478        typ: &ColumnType,
479        writer: CellWriter<'b>,
480    ) -> Result<WrittenCellProof<'b>, SerializationError> {
481        serialize_sequence(
482            std::any::type_name::<Self>(),
483            self.len(),
484            self.iter(),
485            typ,
486            writer,
487        )
488    }
489}
490impl<K: SerializeValue, V: SerializeValue, S: BuildHasher> SerializeValue for HashMap<K, V, S> {
491    fn serialize<'b>(
492        &self,
493        typ: &ColumnType,
494        writer: CellWriter<'b>,
495    ) -> Result<WrittenCellProof<'b>, SerializationError> {
496        serialize_mapping(
497            std::any::type_name::<Self>(),
498            self.len(),
499            self.iter(),
500            typ,
501            writer,
502        )
503    }
504}
505impl<V: SerializeValue> SerializeValue for BTreeSet<V> {
506    fn serialize<'b>(
507        &self,
508        typ: &ColumnType,
509        writer: CellWriter<'b>,
510    ) -> Result<WrittenCellProof<'b>, SerializationError> {
511        serialize_sequence(
512            std::any::type_name::<Self>(),
513            self.len(),
514            self.iter(),
515            typ,
516            writer,
517        )
518    }
519}
520impl<K: SerializeValue, V: SerializeValue> SerializeValue for BTreeMap<K, V> {
521    fn serialize<'b>(
522        &self,
523        typ: &ColumnType,
524        writer: CellWriter<'b>,
525    ) -> Result<WrittenCellProof<'b>, SerializationError> {
526        serialize_mapping(
527            std::any::type_name::<Self>(),
528            self.len(),
529            self.iter(),
530            typ,
531            writer,
532        )
533    }
534}
535impl<T: SerializeValue> SerializeValue for Vec<T> {
536    fn serialize<'b>(
537        &self,
538        typ: &ColumnType,
539        writer: CellWriter<'b>,
540    ) -> Result<WrittenCellProof<'b>, SerializationError> {
541        match typ {
542            ColumnType::Collection {
543                typ: CollectionType::List(_) | CollectionType::Set(_),
544                ..
545            } => serialize_sequence(
546                std::any::type_name::<Self>(),
547                self.len(),
548                self.iter(),
549                typ,
550                writer,
551            ),
552
553            ColumnType::Vector {
554                typ: element_type,
555                dimensions,
556            } => serialize_vector(
557                std::any::type_name::<Self>(),
558                self.len(),
559                self.iter(),
560                element_type,
561                *dimensions,
562                typ,
563                writer,
564            ),
565
566            _ => Err(mk_typck_err_named(
567                std::any::type_name::<Self>(),
568                typ,
569                SetOrListTypeCheckErrorKind::NotSetOrList,
570            )),
571        }
572    }
573}
574impl<T: SerializeValue> SerializeValue for [T] {
575    fn serialize<'b>(
576        &self,
577        typ: &ColumnType,
578        writer: CellWriter<'b>,
579    ) -> Result<WrittenCellProof<'b>, SerializationError> {
580        match typ {
581            ColumnType::Collection {
582                typ: CollectionType::List(_) | CollectionType::Set(_),
583                ..
584            } => serialize_sequence(
585                std::any::type_name::<Self>(),
586                self.len(),
587                self.iter(),
588                typ,
589                writer,
590            ),
591
592            ColumnType::Vector {
593                typ: element_type,
594                dimensions,
595            } => serialize_vector(
596                std::any::type_name::<Self>(),
597                self.len(),
598                self.iter(),
599                element_type,
600                *dimensions,
601                typ,
602                writer,
603            ),
604
605            _ => Err(mk_typck_err_named(
606                std::any::type_name::<Self>(),
607                typ,
608                SetOrListTypeCheckErrorKind::NotSetOrList,
609            )),
610        }
611    }
612}
613impl SerializeValue for CqlValue {
614    fn serialize<'b>(
615        &self,
616        typ: &ColumnType,
617        writer: CellWriter<'b>,
618    ) -> Result<WrittenCellProof<'b>, SerializationError> {
619        serialize_cql_value(self, typ, writer).map_err(fix_rust_name_in_err::<Self>)
620    }
621}
622
623fn serialize_cql_value<'b>(
624    value: &CqlValue,
625    typ: &ColumnType,
626    writer: CellWriter<'b>,
627) -> Result<WrittenCellProof<'b>, SerializationError> {
628    match value {
629        CqlValue::Ascii(a) => <_ as SerializeValue>::serialize(&a, typ, writer),
630        CqlValue::Boolean(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
631        CqlValue::Blob(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
632        CqlValue::Counter(c) => <_ as SerializeValue>::serialize(&c, typ, writer),
633        CqlValue::Decimal(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
634        CqlValue::Date(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
635        CqlValue::Double(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
636        CqlValue::Duration(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
637        CqlValue::Empty => {
638            if !typ.supports_special_empty_value() {
639                return Err(mk_typck_err::<CqlValue>(
640                    typ,
641                    BuiltinTypeCheckErrorKind::NotEmptyable,
642                ));
643            }
644            Ok(writer.set_value(&[]).unwrap())
645        }
646        CqlValue::Float(f) => <_ as SerializeValue>::serialize(&f, typ, writer),
647        CqlValue::Int(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
648        CqlValue::BigInt(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
649        CqlValue::Text(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
650        CqlValue::Timestamp(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
651        CqlValue::Inet(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
652        CqlValue::List(l) => <_ as SerializeValue>::serialize(&l, typ, writer),
653        CqlValue::Map(m) => serialize_mapping(
654            std::any::type_name::<CqlValue>(),
655            m.len(),
656            m.iter().map(|p| (&p.0, &p.1)),
657            typ,
658            writer,
659        ),
660        CqlValue::Set(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
661        CqlValue::UserDefinedType {
662            keyspace,
663            name: type_name,
664            fields,
665        } => serialize_udt(typ, keyspace, type_name, fields, writer),
666        CqlValue::SmallInt(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
667        CqlValue::TinyInt(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
668        CqlValue::Time(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
669        CqlValue::Timeuuid(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
670        CqlValue::Tuple(t) => {
671            // We allow serializing tuples that have less fields
672            // than the database tuple, but not the other way around.
673            let fields = match typ {
674                ColumnType::Tuple(fields) => {
675                    if fields.len() < t.len() {
676                        return Err(mk_typck_err::<CqlValue>(
677                            typ,
678                            TupleTypeCheckErrorKind::WrongElementCount {
679                                rust_type_el_count: t.len(),
680                                cql_type_el_count: fields.len(),
681                            },
682                        ));
683                    }
684                    fields
685                }
686                _ => {
687                    return Err(mk_typck_err::<CqlValue>(
688                        typ,
689                        TupleTypeCheckErrorKind::NotTuple,
690                    ));
691                }
692            };
693            serialize_tuple_like(typ, fields.iter(), t.iter(), writer)
694        }
695        CqlValue::Uuid(u) => <_ as SerializeValue>::serialize(&u, typ, writer),
696        CqlValue::Varint(v) => <_ as SerializeValue>::serialize(&v, typ, writer),
697        CqlValue::Vector(v) => <_ as SerializeValue>::serialize(&v, typ, writer),
698    }
699}
700
701fn fix_rust_name_in_err<RustT>(mut err: SerializationError) -> SerializationError {
702    // The purpose of this function is to change the `rust_name` field
703    // in the error to the given one. Most of the time, the `err` given to the
704    // function here will be the sole owner of the data, so theoretically
705    // we could fix this in place.
706
707    let rust_name = std::any::type_name::<RustT>();
708
709    match Arc::get_mut(&mut err.0) {
710        Some(err_mut) => {
711            if let Some(err) = err_mut.downcast_mut::<BuiltinTypeCheckError>() {
712                err.rust_name = rust_name;
713            } else if let Some(err) = err_mut.downcast_mut::<BuiltinSerializationError>() {
714                err.rust_name = rust_name;
715            }
716        }
717        None => {
718            // The `None` case shouldn't happen considering how we are using
719            // the function in the code now, but let's provide it here anyway
720            // for correctness.
721            if let Some(err) = err.0.downcast_ref::<BuiltinTypeCheckError>()
722                && err.rust_name != rust_name
723            {
724                return SerializationError::new(BuiltinTypeCheckError {
725                    rust_name,
726                    ..err.clone()
727                });
728            }
729
730            if let Some(err) = err.0.downcast_ref::<BuiltinSerializationError>()
731                && err.rust_name != rust_name
732            {
733                return SerializationError::new(BuiltinSerializationError {
734                    rust_name,
735                    ..err.clone()
736                });
737            }
738        }
739    };
740
741    err
742}
743
744fn serialize_udt<'b>(
745    typ: &ColumnType,
746    keyspace: &str,
747    type_name: &str,
748    values: &[(String, Option<CqlValue>)],
749    writer: CellWriter<'b>,
750) -> Result<WrittenCellProof<'b>, SerializationError> {
751    let (dst_type_name, dst_keyspace, field_types) = match typ {
752        ColumnType::UserDefinedType {
753            definition: udt, ..
754        } => (&udt.name, &udt.keyspace, &udt.field_types),
755        _ => return Err(mk_typck_err::<CqlValue>(typ, UdtTypeCheckErrorKind::NotUdt)),
756    };
757
758    if keyspace != dst_keyspace || type_name != dst_type_name {
759        return Err(mk_typck_err::<CqlValue>(
760            typ,
761            UdtTypeCheckErrorKind::NameMismatch {
762                keyspace: dst_keyspace.clone().into_owned(),
763                type_name: dst_type_name.clone().into_owned(),
764            },
765        ));
766    }
767
768    // Allow columns present in the CQL type which are not present in CqlValue,
769    // but not the other way around
770    let mut indexed_fields: HashMap<_, _> = values.iter().map(|(k, v)| (k.as_str(), v)).collect();
771
772    let mut builder = writer.into_value_builder();
773    for (fname, ftyp) in field_types {
774        // Take a value from the original list.
775        // If a field is missing, write null instead.
776        let fvalue = indexed_fields
777            .remove(fname.deref())
778            .and_then(|x| x.as_ref());
779
780        let writer = builder.make_sub_writer();
781        match fvalue {
782            None => writer.set_null(),
783            Some(v) => serialize_cql_value(v, ftyp, writer).map_err(|err| {
784                let err = fix_rust_name_in_err::<CqlValue>(err);
785                mk_ser_err::<CqlValue>(
786                    typ,
787                    UdtSerializationErrorKind::FieldSerializationFailed {
788                        field_name: fname.clone().into_owned(),
789                        err,
790                    },
791                )
792            })?,
793        };
794    }
795
796    // If there are some leftover fields, it's an error.
797    if !indexed_fields.is_empty() {
798        // In order to have deterministic errors, return an error about
799        // the lexicographically smallest field.
800        let fname = indexed_fields.keys().min().unwrap();
801        return Err(mk_typck_err::<CqlValue>(
802            typ,
803            UdtTypeCheckErrorKind::NoSuchFieldInUdt {
804                field_name: fname.to_string(),
805            },
806        ));
807    }
808
809    builder
810        .finish()
811        .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
812}
813
814fn serialize_tuple_like<'t, 'b>(
815    typ: &ColumnType,
816    field_types: impl Iterator<Item = &'t ColumnType<'t>>,
817    field_values: impl Iterator<Item = &'t Option<CqlValue>>,
818    writer: CellWriter<'b>,
819) -> Result<WrittenCellProof<'b>, SerializationError> {
820    let mut builder = writer.into_value_builder();
821
822    for (index, (el, el_typ)) in field_values.zip(field_types).enumerate() {
823        let sub = builder.make_sub_writer();
824        match el {
825            None => sub.set_null(),
826            Some(el) => serialize_cql_value(el, el_typ, sub).map_err(|err| {
827                let err = fix_rust_name_in_err::<CqlValue>(err);
828                mk_ser_err::<CqlValue>(
829                    typ,
830                    TupleSerializationErrorKind::ElementSerializationFailed { index, err },
831                )
832            })?,
833        };
834    }
835
836    builder
837        .finish()
838        .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
839}
840
841macro_rules! impl_tuple {
842    (
843        $($typs:ident),*;
844        $($fidents:ident),*;
845        $($tidents:ident),*;
846        $length:expr
847    ) => {
848        impl<$($typs: SerializeValue),*> SerializeValue for ($($typs,)*) {
849            fn serialize<'b>(
850                &self,
851                typ: &ColumnType,
852                writer: CellWriter<'b>,
853            ) -> Result<WrittenCellProof<'b>, SerializationError> {
854                let ($($tidents,)*) = match typ {
855                    ColumnType::Tuple(typs) => match typs.as_slice() {
856                        [$($tidents),*] => ($($tidents,)*),
857                        _ => return Err(mk_typck_err::<Self>(
858                            typ,
859                            TupleTypeCheckErrorKind::WrongElementCount {
860                                rust_type_el_count: $length,
861                                cql_type_el_count: typs.len(),
862                            }
863                        ))
864                    }
865                    _ => return Err(mk_typck_err::<Self>(
866                        typ,
867                        TupleTypeCheckErrorKind::NotTuple,
868                    ))
869                };
870                let ($($fidents,)*) = self;
871                let mut builder = writer.into_value_builder();
872                let index = 0;
873                $(
874                    <$typs as SerializeValue>::serialize($fidents, $tidents, builder.make_sub_writer())
875                        .map_err(|err| mk_ser_err::<Self>(
876                            typ,
877                            TupleSerializationErrorKind::ElementSerializationFailed {
878                                index,
879                                err,
880                            }
881                        ))?;
882                    let index = index + 1;
883                )*
884                let _ = index;
885                builder
886                    .finish()
887                    .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))
888            }
889        }
890    };
891}
892
893macro_rules! impl_tuples {
894    (;;;$length:expr) => {};
895    (
896        $typ:ident$(, $($typs:ident),*)?;
897        $fident:ident$(, $($fidents:ident),*)?;
898        $tident:ident$(, $($tidents:ident),*)?;
899        $length:expr
900    ) => {
901        impl_tuples!(
902            $($($typs),*)?;
903            $($($fidents),*)?;
904            $($($tidents),*)?;
905            $length - 1
906        );
907        impl_tuple!(
908            $typ$(, $($typs),*)?;
909            $fident$(, $($fidents),*)?;
910            $tident$(, $($tidents),*)?;
911            $length
912        );
913    };
914}
915
916impl_tuples!(
917    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15;
918    f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15;
919    t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15;
920    16
921);
922
923fn serialize_sequence<'t, 'b, T: SerializeValue + 't>(
924    rust_name: &'static str,
925    len: usize,
926    iter: impl Iterator<Item = &'t T>,
927    typ: &ColumnType,
928    writer: CellWriter<'b>,
929) -> Result<WrittenCellProof<'b>, SerializationError> {
930    let elt = match typ {
931        ColumnType::Collection {
932            frozen: _,
933            typ: CollectionType::List(elt),
934        }
935        | ColumnType::Collection {
936            frozen: _,
937            typ: CollectionType::Set(elt),
938        } => elt,
939        _ => {
940            return Err(mk_typck_err_named(
941                rust_name,
942                typ,
943                SetOrListTypeCheckErrorKind::NotSetOrList,
944            ));
945        }
946    };
947
948    let mut builder = writer.into_value_builder();
949
950    let element_count: i32 = len.try_into().map_err(|_| {
951        mk_ser_err_named(
952            rust_name,
953            typ,
954            SetOrListSerializationErrorKind::TooManyElements,
955        )
956    })?;
957    builder.append_bytes(&element_count.to_be_bytes());
958
959    for el in iter {
960        T::serialize(el, elt, builder.make_sub_writer()).map_err(|err| {
961            mk_ser_err_named(
962                rust_name,
963                typ,
964                SetOrListSerializationErrorKind::ElementSerializationFailed(err),
965            )
966        })?;
967    }
968
969    builder
970        .finish()
971        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
972}
973
974fn serialize_next_constant_length_elem<'t, T: SerializeValue + 't>(
975    rust_name: &'static str,
976    element_type: &ColumnType,
977    typ: &ColumnType,
978    builder: &mut CellValueBuilder,
979    element: &'t T,
980) -> Result<(), SerializationError> {
981    T::serialize(
982        element,
983        element_type,
984        builder.make_sub_writer_without_size(),
985    )
986    .map_err(|err| {
987        mk_ser_err_named(
988            rust_name,
989            typ,
990            VectorSerializationErrorKind::ElementSerializationFailed(err),
991        )
992    })?;
993    Ok(())
994}
995
996fn serialize_next_variable_length_elem<'t, T: SerializeValue + 't>(
997    rust_name: &'static str,
998    element_type: &ColumnType,
999    typ: &ColumnType,
1000    builder: &mut CellValueBuilder,
1001    element: &'t T,
1002) -> Result<(), SerializationError> {
1003    let mut element_buffer = Vec::new();
1004    let inner_writer = CellWriter::new_without_size(&mut element_buffer);
1005    T::serialize(element, element_type, inner_writer).map_err(|err| {
1006        mk_ser_err_named(
1007            rust_name,
1008            typ,
1009            VectorSerializationErrorKind::ElementSerializationFailed(err),
1010        )
1011    })?;
1012    let mut element_length_buffer = Vec::new();
1013    unsigned_vint_encode(
1014        element_buffer.len().try_into().unwrap(),
1015        &mut element_length_buffer,
1016    );
1017    builder.append_bytes(element_length_buffer.as_slice());
1018    builder.append_bytes(element_buffer.as_slice());
1019    Ok(())
1020}
1021
1022fn serialize_vector<'t, 'b, T: SerializeValue + 't>(
1023    rust_name: &'static str,
1024    len: usize,
1025    iter: impl Iterator<Item = &'t T>,
1026    element_type: &ColumnType,
1027    dimensions: u16,
1028    typ: &ColumnType,
1029    writer: CellWriter<'b>,
1030) -> Result<WrittenCellProof<'b>, SerializationError> {
1031    if len != dimensions as usize {
1032        return Err(mk_ser_err_named(
1033            rust_name,
1034            typ,
1035            VectorSerializationErrorKind::InvalidNumberOfElements(len, dimensions),
1036        ));
1037    }
1038    let mut builder = writer.into_value_builder();
1039    match element_type.type_size() {
1040        Some(_) => {
1041            for element in iter {
1042                serialize_next_constant_length_elem(
1043                    rust_name,
1044                    element_type,
1045                    typ,
1046                    &mut builder,
1047                    element,
1048                )?;
1049            }
1050        }
1051        None => {
1052            for element in iter {
1053                serialize_next_variable_length_elem(
1054                    rust_name,
1055                    element_type,
1056                    typ,
1057                    &mut builder,
1058                    element,
1059                )?;
1060            }
1061        }
1062    }
1063
1064    builder
1065        .finish()
1066        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
1067}
1068
1069fn serialize_mapping<'t, 'b, K: SerializeValue + 't, V: SerializeValue + 't>(
1070    rust_name: &'static str,
1071    len: usize,
1072    iter: impl Iterator<Item = (&'t K, &'t V)>,
1073    typ: &ColumnType,
1074    writer: CellWriter<'b>,
1075) -> Result<WrittenCellProof<'b>, SerializationError> {
1076    let (ktyp, vtyp) = match typ {
1077        ColumnType::Collection {
1078            frozen: _,
1079            typ: CollectionType::Map(k, v),
1080        } => (k, v),
1081        _ => {
1082            return Err(mk_typck_err_named(
1083                rust_name,
1084                typ,
1085                MapTypeCheckErrorKind::NotMap,
1086            ));
1087        }
1088    };
1089
1090    let mut builder = writer.into_value_builder();
1091
1092    let element_count: i32 = len.try_into().map_err(|_| {
1093        mk_ser_err_named(rust_name, typ, MapSerializationErrorKind::TooManyElements)
1094    })?;
1095    builder.append_bytes(&element_count.to_be_bytes());
1096
1097    for (k, v) in iter {
1098        K::serialize(k, ktyp, builder.make_sub_writer()).map_err(|err| {
1099            mk_ser_err_named(
1100                rust_name,
1101                typ,
1102                MapSerializationErrorKind::KeySerializationFailed(err),
1103            )
1104        })?;
1105        V::serialize(v, vtyp, builder.make_sub_writer()).map_err(|err| {
1106            mk_ser_err_named(
1107                rust_name,
1108                typ,
1109                MapSerializationErrorKind::ValueSerializationFailed(err),
1110            )
1111        })?;
1112    }
1113
1114    builder
1115        .finish()
1116        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
1117}
1118
1119/// Type checking of one of the built-in types failed.
1120#[derive(Debug, Error, Clone)]
1121#[error("Failed to type check Rust type {rust_name} against CQL type {got:?}: {kind}")]
1122pub struct BuiltinTypeCheckError {
1123    /// Name of the Rust type being serialized.
1124    pub rust_name: &'static str,
1125
1126    /// The CQL type that the Rust type was being serialized to.
1127    pub got: ColumnType<'static>,
1128
1129    /// Detailed information about the failure.
1130    pub kind: BuiltinTypeCheckErrorKind,
1131}
1132
1133fn mk_typck_err<T: ?Sized>(
1134    got: &ColumnType,
1135    kind: impl Into<BuiltinTypeCheckErrorKind>,
1136) -> SerializationError {
1137    mk_typck_err_named(std::any::type_name::<T>(), got, kind)
1138}
1139
1140fn mk_typck_err_named(
1141    name: &'static str,
1142    got: &ColumnType,
1143    kind: impl Into<BuiltinTypeCheckErrorKind>,
1144) -> SerializationError {
1145    SerializationError::new(BuiltinTypeCheckError {
1146        rust_name: name,
1147        got: got.clone().into_owned(),
1148        kind: kind.into(),
1149    })
1150}
1151
1152/// Serialization of one of the built-in types failed.
1153#[derive(Debug, Error, Clone)]
1154#[error("Failed to serialize Rust type {rust_name} into CQL type {got:?}: {kind}")]
1155pub struct BuiltinSerializationError {
1156    /// Name of the Rust type being serialized.
1157    pub rust_name: &'static str,
1158
1159    /// The CQL type that the Rust type was being serialized to.
1160    pub got: ColumnType<'static>,
1161
1162    /// Detailed information about the failure.
1163    pub kind: BuiltinSerializationErrorKind,
1164}
1165
1166pub(crate) fn mk_ser_err<T: ?Sized>(
1167    got: &ColumnType,
1168    kind: impl Into<BuiltinSerializationErrorKind>,
1169) -> SerializationError {
1170    mk_ser_err_named(std::any::type_name::<T>(), got, kind)
1171}
1172
1173fn mk_ser_err_named(
1174    name: &'static str,
1175    got: &ColumnType,
1176    kind: impl Into<BuiltinSerializationErrorKind>,
1177) -> SerializationError {
1178    SerializationError::new(BuiltinSerializationError {
1179        rust_name: name,
1180        got: got.clone().into_owned(),
1181        kind: kind.into(),
1182    })
1183}
1184
1185/// Describes why type checking some of the built-in types has failed.
1186#[derive(Debug, Clone)]
1187#[non_exhaustive]
1188pub enum BuiltinTypeCheckErrorKind {
1189    /// Expected one from a list of particular types.
1190    MismatchedType {
1191        /// The list of types that the Rust type can serialize as.
1192        expected: &'static [ColumnType<'static>],
1193    },
1194
1195    /// Expected a type that can be empty.
1196    NotEmptyable,
1197
1198    /// A type check failure specific to a CQL set or list.
1199    SetOrListError(SetOrListTypeCheckErrorKind),
1200
1201    /// A type check failure specific to a CQL map.
1202    MapError(MapTypeCheckErrorKind),
1203
1204    /// A type check failure specific to a CQL tuple.
1205    TupleError(TupleTypeCheckErrorKind),
1206
1207    /// A type check failure specific to a CQL UDT.
1208    UdtError(UdtTypeCheckErrorKind),
1209}
1210
1211impl From<SetOrListTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1212    fn from(value: SetOrListTypeCheckErrorKind) -> Self {
1213        BuiltinTypeCheckErrorKind::SetOrListError(value)
1214    }
1215}
1216
1217impl From<MapTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1218    fn from(value: MapTypeCheckErrorKind) -> Self {
1219        BuiltinTypeCheckErrorKind::MapError(value)
1220    }
1221}
1222
1223impl From<TupleTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1224    fn from(value: TupleTypeCheckErrorKind) -> Self {
1225        BuiltinTypeCheckErrorKind::TupleError(value)
1226    }
1227}
1228
1229impl From<UdtTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1230    fn from(value: UdtTypeCheckErrorKind) -> Self {
1231        BuiltinTypeCheckErrorKind::UdtError(value)
1232    }
1233}
1234
1235impl Display for BuiltinTypeCheckErrorKind {
1236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1237        match self {
1238            BuiltinTypeCheckErrorKind::MismatchedType { expected } => {
1239                write!(f, "expected one of the CQL types: {expected:?}")
1240            }
1241            BuiltinTypeCheckErrorKind::NotEmptyable => {
1242                f.write_str("the separate empty representation is not valid for this type")
1243            }
1244            BuiltinTypeCheckErrorKind::SetOrListError(err) => err.fmt(f),
1245            BuiltinTypeCheckErrorKind::MapError(err) => err.fmt(f),
1246            BuiltinTypeCheckErrorKind::TupleError(err) => err.fmt(f),
1247            BuiltinTypeCheckErrorKind::UdtError(err) => err.fmt(f),
1248        }
1249    }
1250}
1251
1252/// Describes why serialization of some of the built-in types has failed.
1253#[derive(Debug, Clone)]
1254#[non_exhaustive]
1255pub enum BuiltinSerializationErrorKind {
1256    /// The size of the Rust value is too large to fit in the CQL serialization
1257    /// format (over i32::MAX bytes).
1258    SizeOverflow,
1259
1260    /// The Rust value is out of range supported by the CQL type.
1261    ValueOverflow,
1262
1263    /// A serialization failure specific to a CQL set or list.
1264    SetOrListError(SetOrListSerializationErrorKind),
1265
1266    /// A serialization failure specific to a CQL set or list.
1267    VectorError(VectorSerializationErrorKind),
1268
1269    /// A serialization failure specific to a CQL map.
1270    MapError(MapSerializationErrorKind),
1271
1272    /// A serialization failure specific to a CQL tuple.
1273    TupleError(TupleSerializationErrorKind),
1274
1275    /// A serialization failure specific to a CQL UDT.
1276    UdtError(UdtSerializationErrorKind),
1277}
1278
1279impl From<SetOrListSerializationErrorKind> for BuiltinSerializationErrorKind {
1280    fn from(value: SetOrListSerializationErrorKind) -> Self {
1281        BuiltinSerializationErrorKind::SetOrListError(value)
1282    }
1283}
1284
1285impl From<VectorSerializationErrorKind> for BuiltinSerializationErrorKind {
1286    fn from(value: VectorSerializationErrorKind) -> Self {
1287        BuiltinSerializationErrorKind::VectorError(value)
1288    }
1289}
1290
1291impl From<MapSerializationErrorKind> for BuiltinSerializationErrorKind {
1292    fn from(value: MapSerializationErrorKind) -> Self {
1293        BuiltinSerializationErrorKind::MapError(value)
1294    }
1295}
1296
1297impl From<TupleSerializationErrorKind> for BuiltinSerializationErrorKind {
1298    fn from(value: TupleSerializationErrorKind) -> Self {
1299        BuiltinSerializationErrorKind::TupleError(value)
1300    }
1301}
1302
1303impl From<UdtSerializationErrorKind> for BuiltinSerializationErrorKind {
1304    fn from(value: UdtSerializationErrorKind) -> Self {
1305        BuiltinSerializationErrorKind::UdtError(value)
1306    }
1307}
1308
1309impl Display for BuiltinSerializationErrorKind {
1310    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1311        match self {
1312            BuiltinSerializationErrorKind::SizeOverflow => {
1313                f.write_str("the Rust value is too big to be serialized in the CQL protocol format")
1314            }
1315            BuiltinSerializationErrorKind::ValueOverflow => {
1316                f.write_str("the Rust value is out of range supported by the CQL type")
1317            }
1318            BuiltinSerializationErrorKind::SetOrListError(err) => err.fmt(f),
1319            BuiltinSerializationErrorKind::VectorError(err) => err.fmt(f),
1320            BuiltinSerializationErrorKind::MapError(err) => err.fmt(f),
1321            BuiltinSerializationErrorKind::TupleError(err) => err.fmt(f),
1322            BuiltinSerializationErrorKind::UdtError(err) => err.fmt(f),
1323        }
1324    }
1325}
1326
1327/// Describes why type checking of a map type failed.
1328#[derive(Debug, Clone)]
1329#[non_exhaustive]
1330pub enum MapTypeCheckErrorKind {
1331    /// The CQL type is not a map.
1332    NotMap,
1333}
1334
1335impl Display for MapTypeCheckErrorKind {
1336    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1337        match self {
1338            MapTypeCheckErrorKind::NotMap => f.write_str(
1339                "the CQL type the Rust type was attempted to be type checked against was not a map",
1340            ),
1341        }
1342    }
1343}
1344
1345/// Describes why serialization of a map type failed.
1346#[derive(Debug, Clone)]
1347#[non_exhaustive]
1348pub enum MapSerializationErrorKind {
1349    /// The many contains too many items, exceeding the protocol limit (i32::MAX).
1350    TooManyElements,
1351
1352    /// One of the keys in the map failed to serialize.
1353    KeySerializationFailed(SerializationError),
1354
1355    /// One of the values in the map failed to serialize.
1356    ValueSerializationFailed(SerializationError),
1357}
1358
1359impl Display for MapSerializationErrorKind {
1360    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1361        match self {
1362            MapSerializationErrorKind::TooManyElements => {
1363                f.write_str("the map contains too many elements to fit in CQL representation")
1364            }
1365            MapSerializationErrorKind::KeySerializationFailed(err) => {
1366                write!(f, "failed to serialize one of the keys: {err}")
1367            }
1368            MapSerializationErrorKind::ValueSerializationFailed(err) => {
1369                write!(f, "failed to serialize one of the values: {err}")
1370            }
1371        }
1372    }
1373}
1374
1375/// Describes why type checking of a set or list type failed.
1376#[derive(Debug, Clone)]
1377#[non_exhaustive]
1378pub enum SetOrListTypeCheckErrorKind {
1379    /// The CQL type is neither a set, nor a list, nor a vector.
1380    NotSetOrList,
1381}
1382
1383impl Display for SetOrListTypeCheckErrorKind {
1384    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1385        match self {
1386            SetOrListTypeCheckErrorKind::NotSetOrList => {
1387                f.write_str("the CQL type the Rust type was attempted to be type checked against was neither a set, nor a list, nor a vector")
1388            }
1389        }
1390    }
1391}
1392
1393/// Describes why serialization of a set or list type failed.
1394#[derive(Debug, Clone)]
1395#[non_exhaustive]
1396pub enum SetOrListSerializationErrorKind {
1397    /// The set/list contains too many items, exceeding the protocol limit (i32::MAX).
1398    TooManyElements,
1399
1400    /// One of the elements of the set/list failed to serialize.
1401    ElementSerializationFailed(SerializationError),
1402}
1403
1404impl Display for SetOrListSerializationErrorKind {
1405    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1406        match self {
1407            SetOrListSerializationErrorKind::TooManyElements => f.write_str(
1408                "the collection contains too many elements to fit in CQL representation",
1409            ),
1410            SetOrListSerializationErrorKind::ElementSerializationFailed(err) => {
1411                write!(f, "failed to serialize one of the elements: {err}")
1412            }
1413        }
1414    }
1415}
1416
1417/// Describes why serialization of a vector type failed.
1418#[derive(Error, Debug, Clone)]
1419#[non_exhaustive]
1420pub enum VectorSerializationErrorKind {
1421    /// The number of elements in the serialized collection does not match
1422    /// the number of vector dimensions
1423    #[error(
1424        "number of vector elements ({0}) does not match the number of declared dimensions ({1})"
1425    )]
1426    InvalidNumberOfElements(usize, u16),
1427
1428    /// One of the elements of the vector failed to serialize.
1429    #[error("failed to serialize one of the elements: {0}")]
1430    ElementSerializationFailed(SerializationError),
1431}
1432
1433/// Describes why type checking of a tuple failed.
1434#[derive(Debug, Clone)]
1435#[non_exhaustive]
1436pub enum TupleTypeCheckErrorKind {
1437    /// The CQL type is not a tuple.
1438    NotTuple,
1439
1440    /// The tuple has the wrong element count.
1441    ///
1442    /// Note that it is allowed to write a Rust tuple with less elements
1443    /// than the corresponding CQL type, but not more. The additional, unknown
1444    /// elements will be set to null.
1445    WrongElementCount {
1446        /// The number of elements that the Rust tuple has.
1447        rust_type_el_count: usize,
1448
1449        /// The number of elements that the CQL tuple type has.
1450        cql_type_el_count: usize,
1451    },
1452}
1453
1454impl Display for TupleTypeCheckErrorKind {
1455    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1456        match self {
1457            TupleTypeCheckErrorKind::NotTuple => f.write_str(
1458                "the CQL type the Rust type was attempted to be type checked against is not a tuple"
1459            ),
1460            TupleTypeCheckErrorKind::WrongElementCount { rust_type_el_count, cql_type_el_count } => write!(
1461                f,
1462                "wrong tuple element count: CQL type has {cql_type_el_count}, the Rust tuple has {rust_type_el_count}"
1463            ),
1464        }
1465    }
1466}
1467
1468/// Describes why serialize of a tuple failed.
1469#[derive(Debug, Clone)]
1470#[non_exhaustive]
1471pub enum TupleSerializationErrorKind {
1472    /// One of the tuple elements failed to serialize.
1473    ElementSerializationFailed {
1474        /// Index of the tuple element that failed to serialize.
1475        index: usize,
1476
1477        /// The error that caused the tuple field serialization to fail.
1478        err: SerializationError,
1479    },
1480}
1481
1482impl Display for TupleSerializationErrorKind {
1483    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1484        match self {
1485            TupleSerializationErrorKind::ElementSerializationFailed { index, err } => {
1486                write!(f, "element no. {index} failed to serialize: {err}")
1487            }
1488        }
1489    }
1490}
1491
1492/// Describes why type checking of a user defined type failed.
1493#[derive(Debug, Clone)]
1494#[non_exhaustive]
1495pub enum UdtTypeCheckErrorKind {
1496    /// The CQL type is not a user defined type.
1497    NotUdt,
1498
1499    /// The name of the UDT being serialized to does not match.
1500    NameMismatch {
1501        /// Keyspace in which the UDT was defined.
1502        keyspace: String,
1503
1504        /// Name of the UDT.
1505        type_name: String,
1506    },
1507
1508    /// The Rust data does not have a field that is required in the CQL UDT type.
1509    ValueMissingForUdtField {
1510        /// Name of field that the CQL UDT requires but is missing in the Rust struct.
1511        field_name: String,
1512    },
1513
1514    /// The Rust data contains a field that is not present in the UDT.
1515    NoSuchFieldInUdt {
1516        /// Name of the Rust struct field that is missing in the UDT.
1517        field_name: String,
1518    },
1519
1520    /// A different field name was expected at given position.
1521    FieldNameMismatch {
1522        /// The name of the Rust field.
1523        rust_field_name: String,
1524
1525        /// The name of the CQL UDT field.
1526        db_field_name: String,
1527    },
1528}
1529
1530impl Display for UdtTypeCheckErrorKind {
1531    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1532        match self {
1533            UdtTypeCheckErrorKind::NotUdt => f.write_str(
1534                "the CQL type the Rust type was attempted to be type checked against is not a UDT",
1535            ),
1536            UdtTypeCheckErrorKind::NameMismatch {
1537                keyspace,
1538                type_name,
1539            } => write!(
1540                f,
1541                "the Rust UDT name does not match the actual CQL UDT name ({keyspace}.{type_name})"
1542            ),
1543            UdtTypeCheckErrorKind::ValueMissingForUdtField { field_name } => {
1544                write!(
1545                    f,
1546                    "the field {field_name} is missing in the Rust data but is required by the CQL UDT type"
1547                )
1548            }
1549            UdtTypeCheckErrorKind::NoSuchFieldInUdt { field_name } => write!(
1550                f,
1551                "the field {field_name} that is present in the Rust data is not present in the CQL type"
1552            ),
1553            UdtTypeCheckErrorKind::FieldNameMismatch {
1554                rust_field_name,
1555                db_field_name,
1556            } => write!(
1557                f,
1558                "expected field with name {db_field_name} at given position, but the Rust field name is {rust_field_name}"
1559            ),
1560        }
1561    }
1562}
1563
1564/// Describes why serialization of a user defined type failed.
1565#[derive(Debug, Clone)]
1566#[non_exhaustive]
1567pub enum UdtSerializationErrorKind {
1568    /// One of the fields failed to serialize.
1569    FieldSerializationFailed {
1570        /// Name of the field which failed to serialize.
1571        field_name: String,
1572
1573        /// The error that caused the UDT field serialization to fail.
1574        err: SerializationError,
1575    },
1576}
1577
1578impl Display for UdtSerializationErrorKind {
1579    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1580        match self {
1581            UdtSerializationErrorKind::FieldSerializationFailed { field_name, err } => {
1582                write!(f, "field {field_name} failed to serialize: {err}")
1583            }
1584        }
1585    }
1586}
1587
1588mod doctests {
1589    /// ```compile_fail
1590    ///
1591    /// #[derive(scylla_macros::SerializeValue)]
1592    /// #[scylla(crate = scylla_cql, skip_name_checks)]
1593    /// struct TestUdt {}
1594    /// ```
1595    fn _test_udt_bad_attributes_skip_name_check_requires_enforce_order() {}
1596
1597    /// ```compile_fail
1598    ///
1599    /// #[derive(scylla_macros::SerializeValue)]
1600    /// #[scylla(crate = scylla_cql, flavor = "enforce_order", skip_name_checks)]
1601    /// struct TestUdt {
1602    ///     #[scylla(rename = "b")]
1603    ///     a: i32,
1604    /// }
1605    /// ```
1606    fn _test_udt_bad_attributes_skip_name_check_conflicts_with_rename() {}
1607
1608    /// ```compile_fail
1609    ///
1610    /// #[derive(scylla_macros::SerializeValue)]
1611    /// #[scylla(crate = scylla_cql)]
1612    /// struct TestUdt {
1613    ///     #[scylla(rename = "b")]
1614    ///     a: i32,
1615    ///     b: String,
1616    /// }
1617    /// ```
1618    fn _test_udt_bad_attributes_rename_collision_with_field() {}
1619
1620    /// ```compile_fail
1621    ///
1622    /// #[derive(scylla_macros::SerializeValue)]
1623    /// #[scylla(crate = scylla_cql)]
1624    /// struct TestUdt {
1625    ///     #[scylla(rename = "c")]
1626    ///     a: i32,
1627    ///     #[scylla(rename = "c")]
1628    ///     b: String,
1629    /// }
1630    /// ```
1631    fn _test_udt_bad_attributes_rename_collision_with_another_rename() {}
1632
1633    /// ```compile_fail
1634    ///
1635    /// #[derive(scylla_macros::SerializeValue)]
1636    /// #[scylla(crate = scylla_cql, flavor = "enforce_order", skip_name_checks)]
1637    /// struct TestUdt {
1638    ///     a: i32,
1639    ///     #[scylla(allow_missing)]
1640    ///     b: bool,
1641    ///     c: String,
1642    /// }
1643    /// ```
1644    fn _test_udt_bad_attributes_name_skip_name_checks_limitations_on_allow_missing() {}
1645
1646    /// ```
1647    ///
1648    /// #[derive(scylla_macros::SerializeValue)]
1649    /// #[scylla(crate = scylla_cql, flavor = "enforce_order", skip_name_checks)]
1650    /// struct TestUdt {
1651    ///     a: i32,
1652    ///     #[scylla(allow_missing)]
1653    ///     b: bool,
1654    ///     #[scylla(allow_missing)]
1655    ///     c: String,
1656    /// }
1657    /// ```
1658    fn _test_udt_good_attributes_name_skip_name_checks_limitations_on_allow_missing() {}
1659
1660    /// ```
1661    /// #[derive(scylla_macros::SerializeValue)]
1662    /// #[scylla(crate = scylla_cql)]
1663    /// struct TestUdt {
1664    ///     a: i32,
1665    ///     #[scylla(allow_missing)]
1666    ///     b: bool,
1667    ///     c: String,
1668    /// }
1669    /// ```
1670    fn _test_udt_unordered_flavour_no_limitations_on_allow_missing() {}
1671
1672    /// ```
1673    /// #[derive(scylla_macros::SerializeValue)]
1674    /// #[scylla(crate = scylla_cql)]
1675    /// struct TestUdt {
1676    ///     a: i32,
1677    ///     #[scylla(default_when_null)]
1678    ///     b: bool,
1679    ///     c: String,
1680    /// }
1681    /// ```
1682    fn _test_udt_default_when_null_is_accepted() {}
1683}
1684
1685#[cfg(test)]
1686#[path = "value_tests.rs"]
1687pub(crate) mod tests;