Skip to main content

scylla_cql_core/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    #[deny(clippy::wildcard_enum_match_arm)]
629    match value {
630        CqlValue::Ascii(a) => <_ as SerializeValue>::serialize(&a, typ, writer),
631        CqlValue::Boolean(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
632        CqlValue::Blob(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
633        CqlValue::Counter(c) => <_ as SerializeValue>::serialize(&c, typ, writer),
634        CqlValue::Decimal(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
635        CqlValue::Date(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
636        CqlValue::Double(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
637        CqlValue::Duration(d) => <_ as SerializeValue>::serialize(&d, typ, writer),
638        CqlValue::Empty => {
639            if !typ.supports_special_empty_value() {
640                return Err(mk_typck_err::<CqlValue>(
641                    typ,
642                    BuiltinTypeCheckErrorKind::NotEmptyable,
643                ));
644            }
645            Ok(writer.set_value(&[]).unwrap())
646        }
647        CqlValue::Float(f) => <_ as SerializeValue>::serialize(&f, typ, writer),
648        CqlValue::Int(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
649        CqlValue::BigInt(b) => <_ as SerializeValue>::serialize(&b, typ, writer),
650        CqlValue::Text(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
651        CqlValue::Timestamp(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
652        CqlValue::Inet(i) => <_ as SerializeValue>::serialize(&i, typ, writer),
653        CqlValue::List(l) => <_ as SerializeValue>::serialize(&l, typ, writer),
654        CqlValue::Map(m) => serialize_mapping(
655            std::any::type_name::<CqlValue>(),
656            m.len(),
657            m.iter().map(|p| (&p.0, &p.1)),
658            typ,
659            writer,
660        ),
661        CqlValue::Set(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
662        CqlValue::UserDefinedType {
663            keyspace,
664            name: type_name,
665            fields,
666        } => serialize_udt(typ, keyspace, type_name, fields, writer),
667        CqlValue::SmallInt(s) => <_ as SerializeValue>::serialize(&s, typ, writer),
668        CqlValue::TinyInt(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
669        CqlValue::Time(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
670        CqlValue::Timeuuid(t) => <_ as SerializeValue>::serialize(&t, typ, writer),
671        CqlValue::Tuple(t) => {
672            // We allow serializing tuples that have less fields
673            // than the database tuple, but not the other way around.
674            let fields = {
675                #[deny(clippy::wildcard_enum_match_arm)]
676                match typ {
677                    ColumnType::Tuple(fields) => {
678                        if fields.len() < t.len() {
679                            return Err(mk_typck_err::<CqlValue>(
680                                typ,
681                                TupleTypeCheckErrorKind::WrongElementCount {
682                                    rust_type_el_count: t.len(),
683                                    cql_type_el_count: fields.len(),
684                                },
685                            ));
686                        }
687                        fields
688                    }
689                    ColumnType::Native(_)
690                    | ColumnType::Collection { .. }
691                    | ColumnType::Vector { .. }
692                    | ColumnType::UserDefinedType { .. } => {
693                        return Err(mk_typck_err::<CqlValue>(
694                            typ,
695                            TupleTypeCheckErrorKind::NotTuple,
696                        ));
697                    }
698                }
699            };
700            serialize_tuple_like(typ, fields.iter(), t.iter(), writer)
701        }
702        CqlValue::Uuid(u) => <_ as SerializeValue>::serialize(&u, typ, writer),
703        CqlValue::Varint(v) => <_ as SerializeValue>::serialize(&v, typ, writer),
704        CqlValue::Vector(v) => <_ as SerializeValue>::serialize(&v, typ, writer),
705    }
706}
707
708fn fix_rust_name_in_err<RustT>(mut err: SerializationError) -> SerializationError {
709    // The purpose of this function is to change the `rust_name` field
710    // in the error to the given one. Most of the time, the `err` given to the
711    // function here will be the sole owner of the data, so theoretically
712    // we could fix this in place.
713
714    let rust_name = std::any::type_name::<RustT>();
715
716    match Arc::get_mut(&mut err.0) {
717        Some(err_mut) => {
718            if let Some(err) = err_mut.downcast_mut::<BuiltinTypeCheckError>() {
719                err.rust_name = rust_name;
720            } else if let Some(err) = err_mut.downcast_mut::<BuiltinSerializationError>() {
721                err.rust_name = rust_name;
722            }
723        }
724        None => {
725            // The `None` case shouldn't happen considering how we are using
726            // the function in the code now, but let's provide it here anyway
727            // for correctness.
728            if let Some(err) = err.0.downcast_ref::<BuiltinTypeCheckError>()
729                && err.rust_name != rust_name
730            {
731                return SerializationError::new(BuiltinTypeCheckError {
732                    rust_name,
733                    ..err.clone()
734                });
735            }
736            if let Some(err) = err.0.downcast_ref::<BuiltinSerializationError>()
737                && err.rust_name != rust_name
738            {
739                return SerializationError::new(BuiltinSerializationError {
740                    rust_name,
741                    ..err.clone()
742                });
743            }
744        }
745    };
746
747    err
748}
749
750fn serialize_udt<'b>(
751    typ: &ColumnType,
752    keyspace: &str,
753    type_name: &str,
754    values: &[(String, Option<CqlValue>)],
755    writer: CellWriter<'b>,
756) -> Result<WrittenCellProof<'b>, SerializationError> {
757    let (dst_type_name, dst_keyspace, field_types) = match typ {
758        ColumnType::UserDefinedType {
759            definition: udt, ..
760        } => (&udt.name, &udt.keyspace, &udt.field_types),
761        _ => return Err(mk_typck_err::<CqlValue>(typ, UdtTypeCheckErrorKind::NotUdt)),
762    };
763
764    if keyspace != dst_keyspace || type_name != dst_type_name {
765        return Err(mk_typck_err::<CqlValue>(
766            typ,
767            UdtTypeCheckErrorKind::NameMismatch {
768                keyspace: dst_keyspace.clone().into_owned(),
769                type_name: dst_type_name.clone().into_owned(),
770            },
771        ));
772    }
773
774    // Allow columns present in the CQL type which are not present in CqlValue,
775    // but not the other way around
776    let mut indexed_fields: HashMap<_, _> = values.iter().map(|(k, v)| (k.as_str(), v)).collect();
777
778    let mut builder = writer.into_value_builder();
779    for (fname, ftyp) in field_types {
780        // Take a value from the original list.
781        // If a field is missing, write null instead.
782        let fvalue = indexed_fields
783            .remove(fname.deref())
784            .and_then(|x| x.as_ref());
785
786        let writer = builder.make_sub_writer();
787        match fvalue {
788            None => writer.set_null(),
789            Some(v) => serialize_cql_value(v, ftyp, writer).map_err(|err| {
790                let err = fix_rust_name_in_err::<CqlValue>(err);
791                mk_ser_err::<CqlValue>(
792                    typ,
793                    UdtSerializationErrorKind::FieldSerializationFailed {
794                        field_name: fname.clone().into_owned(),
795                        err,
796                    },
797                )
798            })?,
799        };
800    }
801
802    // If there are some leftover fields, it's an error.
803    if !indexed_fields.is_empty() {
804        // In order to have deterministic errors, return an error about
805        // the lexicographically smallest field.
806        let fname = indexed_fields.keys().min().unwrap();
807        return Err(mk_typck_err::<CqlValue>(
808            typ,
809            UdtTypeCheckErrorKind::NoSuchFieldInUdt {
810                field_name: fname.to_string(),
811            },
812        ));
813    }
814
815    builder
816        .finish()
817        .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
818}
819
820fn serialize_tuple_like<'t, 'b>(
821    typ: &ColumnType,
822    field_types: impl Iterator<Item = &'t ColumnType<'t>>,
823    field_values: impl Iterator<Item = &'t Option<CqlValue>>,
824    writer: CellWriter<'b>,
825) -> Result<WrittenCellProof<'b>, SerializationError> {
826    let mut builder = writer.into_value_builder();
827
828    for (index, (el, el_typ)) in field_values.zip(field_types).enumerate() {
829        let sub = builder.make_sub_writer();
830        match el {
831            None => sub.set_null(),
832            Some(el) => serialize_cql_value(el, el_typ, sub).map_err(|err| {
833                let err = fix_rust_name_in_err::<CqlValue>(err);
834                mk_ser_err::<CqlValue>(
835                    typ,
836                    TupleSerializationErrorKind::ElementSerializationFailed { index, err },
837                )
838            })?,
839        };
840    }
841
842    builder
843        .finish()
844        .map_err(|_| mk_ser_err::<CqlValue>(typ, BuiltinSerializationErrorKind::SizeOverflow))
845}
846
847macro_rules! impl_tuple {
848    (
849        $($typs:ident),*;
850        $($fidents:ident),*;
851        $($tidents:ident),*;
852        $length:expr
853    ) => {
854        impl<$($typs: SerializeValue),*> SerializeValue for ($($typs,)*) {
855            fn serialize<'b>(
856                &self,
857                typ: &ColumnType,
858                writer: CellWriter<'b>,
859            ) -> Result<WrittenCellProof<'b>, SerializationError> {
860                let ($($tidents,)*) = match typ {
861                    ColumnType::Tuple(typs) => match typs.as_slice() {
862                        // Allow CQL tuples with more fields than the Rust tuple.
863                        // The extra fields will simply not be serialized (treated as null by the server).
864                        // This mirrors how CqlValue::Tuple serialization works.
865                        [$($tidents),*, ..] => ($($tidents,)*),
866                        _ => return Err(mk_typck_err::<Self>(
867                            typ,
868                            TupleTypeCheckErrorKind::WrongElementCount {
869                                rust_type_el_count: $length,
870                                cql_type_el_count: typs.len(),
871                            }
872                        ))
873                    }
874                    _ => return Err(mk_typck_err::<Self>(
875                        typ,
876                        TupleTypeCheckErrorKind::NotTuple,
877                    ))
878                };
879                let ($($fidents,)*) = self;
880                let mut builder = writer.into_value_builder();
881                let index = 0;
882                $(
883                    <$typs as SerializeValue>::serialize($fidents, $tidents, builder.make_sub_writer())
884                        .map_err(|err| mk_ser_err::<Self>(
885                            typ,
886                            TupleSerializationErrorKind::ElementSerializationFailed {
887                                index,
888                                err,
889                            }
890                        ))?;
891                    let index = index + 1;
892                )*
893                let _ = index;
894                builder
895                    .finish()
896                    .map_err(|_| mk_ser_err::<Self>(typ, BuiltinSerializationErrorKind::SizeOverflow))
897            }
898        }
899    };
900}
901
902macro_rules! impl_tuples {
903    (;;;$length:expr) => {};
904    (
905        $typ:ident$(, $($typs:ident),*)?;
906        $fident:ident$(, $($fidents:ident),*)?;
907        $tident:ident$(, $($tidents:ident),*)?;
908        $length:expr
909    ) => {
910        impl_tuples!(
911            $($($typs),*)?;
912            $($($fidents),*)?;
913            $($($tidents),*)?;
914            $length - 1
915        );
916        impl_tuple!(
917            $typ$(, $($typs),*)?;
918            $fident$(, $($fidents),*)?;
919            $tident$(, $($tidents),*)?;
920            $length
921        );
922    };
923}
924
925impl_tuples!(
926    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15;
927    f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15;
928    t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15;
929    16
930);
931
932fn serialize_sequence<'t, 'b, T: SerializeValue + 't>(
933    rust_name: &'static str,
934    len: usize,
935    iter: impl Iterator<Item = &'t T>,
936    typ: &ColumnType,
937    writer: CellWriter<'b>,
938) -> Result<WrittenCellProof<'b>, SerializationError> {
939    let elt = match typ {
940        ColumnType::Collection {
941            frozen: _,
942            typ: CollectionType::List(elt),
943        }
944        | ColumnType::Collection {
945            frozen: _,
946            typ: CollectionType::Set(elt),
947        } => elt,
948        _ => {
949            return Err(mk_typck_err_named(
950                rust_name,
951                typ,
952                SetOrListTypeCheckErrorKind::NotSetOrList,
953            ));
954        }
955    };
956
957    let mut builder = writer.into_value_builder();
958
959    let element_count: i32 = len.try_into().map_err(|_| {
960        mk_ser_err_named(
961            rust_name,
962            typ,
963            SetOrListSerializationErrorKind::TooManyElements,
964        )
965    })?;
966    builder.append_bytes(&element_count.to_be_bytes());
967
968    for el in iter {
969        T::serialize(el, elt, builder.make_sub_writer()).map_err(|err| {
970            mk_ser_err_named(
971                rust_name,
972                typ,
973                SetOrListSerializationErrorKind::ElementSerializationFailed(err),
974            )
975        })?;
976    }
977
978    builder
979        .finish()
980        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
981}
982
983fn serialize_next_constant_length_elem<'t, T: SerializeValue + 't>(
984    rust_name: &'static str,
985    element_type: &ColumnType,
986    typ: &ColumnType,
987    builder: &mut CellValueBuilder,
988    element: &'t T,
989) -> Result<(), SerializationError> {
990    T::serialize(
991        element,
992        element_type,
993        builder.make_sub_writer_without_size(),
994    )
995    .map_err(|err| {
996        mk_ser_err_named(
997            rust_name,
998            typ,
999            VectorSerializationErrorKind::ElementSerializationFailed(err),
1000        )
1001    })?;
1002    Ok(())
1003}
1004
1005fn serialize_next_variable_length_elem<'t, T: SerializeValue + 't>(
1006    rust_name: &'static str,
1007    element_type: &ColumnType,
1008    typ: &ColumnType,
1009    builder: &mut CellValueBuilder,
1010    element: &'t T,
1011) -> Result<(), SerializationError> {
1012    let mut element_buffer = Vec::new();
1013    let inner_writer = CellWriter::new_without_size(&mut element_buffer);
1014    T::serialize(element, element_type, inner_writer).map_err(|err| {
1015        mk_ser_err_named(
1016            rust_name,
1017            typ,
1018            VectorSerializationErrorKind::ElementSerializationFailed(err),
1019        )
1020    })?;
1021    let mut element_length_buffer = Vec::new();
1022    unsigned_vint_encode(
1023        element_buffer.len().try_into().unwrap(),
1024        &mut element_length_buffer,
1025    );
1026    builder.append_bytes(element_length_buffer.as_slice());
1027    builder.append_bytes(element_buffer.as_slice());
1028    Ok(())
1029}
1030
1031fn serialize_vector<'t, 'b, T: SerializeValue + 't>(
1032    rust_name: &'static str,
1033    len: usize,
1034    iter: impl Iterator<Item = &'t T>,
1035    element_type: &ColumnType,
1036    dimensions: u16,
1037    typ: &ColumnType,
1038    writer: CellWriter<'b>,
1039) -> Result<WrittenCellProof<'b>, SerializationError> {
1040    if len != dimensions as usize {
1041        return Err(mk_ser_err_named(
1042            rust_name,
1043            typ,
1044            VectorSerializationErrorKind::InvalidNumberOfElements(len, dimensions),
1045        ));
1046    }
1047    let mut builder = writer.into_value_builder();
1048    match element_type.type_size_for_vector() {
1049        Some(_) => {
1050            for element in iter {
1051                serialize_next_constant_length_elem(
1052                    rust_name,
1053                    element_type,
1054                    typ,
1055                    &mut builder,
1056                    element,
1057                )?;
1058            }
1059        }
1060        None => {
1061            for element in iter {
1062                serialize_next_variable_length_elem(
1063                    rust_name,
1064                    element_type,
1065                    typ,
1066                    &mut builder,
1067                    element,
1068                )?;
1069            }
1070        }
1071    }
1072
1073    builder
1074        .finish()
1075        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
1076}
1077
1078fn serialize_mapping<'t, 'b, K: SerializeValue + 't, V: SerializeValue + 't>(
1079    rust_name: &'static str,
1080    len: usize,
1081    iter: impl Iterator<Item = (&'t K, &'t V)>,
1082    typ: &ColumnType,
1083    writer: CellWriter<'b>,
1084) -> Result<WrittenCellProof<'b>, SerializationError> {
1085    let (ktyp, vtyp) = match typ {
1086        ColumnType::Collection {
1087            frozen: _,
1088            typ: CollectionType::Map(k, v),
1089        } => (k, v),
1090        _ => {
1091            return Err(mk_typck_err_named(
1092                rust_name,
1093                typ,
1094                MapTypeCheckErrorKind::NotMap,
1095            ));
1096        }
1097    };
1098
1099    let mut builder = writer.into_value_builder();
1100
1101    let element_count: i32 = len.try_into().map_err(|_| {
1102        mk_ser_err_named(rust_name, typ, MapSerializationErrorKind::TooManyElements)
1103    })?;
1104    builder.append_bytes(&element_count.to_be_bytes());
1105
1106    for (k, v) in iter {
1107        K::serialize(k, ktyp, builder.make_sub_writer()).map_err(|err| {
1108            mk_ser_err_named(
1109                rust_name,
1110                typ,
1111                MapSerializationErrorKind::KeySerializationFailed(err),
1112            )
1113        })?;
1114        V::serialize(v, vtyp, builder.make_sub_writer()).map_err(|err| {
1115            mk_ser_err_named(
1116                rust_name,
1117                typ,
1118                MapSerializationErrorKind::ValueSerializationFailed(err),
1119            )
1120        })?;
1121    }
1122
1123    builder
1124        .finish()
1125        .map_err(|_| mk_ser_err_named(rust_name, typ, BuiltinSerializationErrorKind::SizeOverflow))
1126}
1127
1128/// Type checking of one of the built-in types failed.
1129#[derive(Debug, Error, Clone)]
1130#[error("Failed to type check Rust type {rust_name} against CQL type {got:?}: {kind}")]
1131pub struct BuiltinTypeCheckError {
1132    /// Name of the Rust type being serialized.
1133    pub rust_name: &'static str,
1134
1135    /// The CQL type that the Rust type was being serialized to.
1136    pub got: ColumnType<'static>,
1137
1138    /// Detailed information about the failure.
1139    pub kind: BuiltinTypeCheckErrorKind,
1140}
1141
1142/// Creates a [`BuiltinTypeCheckError`] with the given kind.
1143pub fn mk_typck_err<T: ?Sized>(
1144    got: &ColumnType,
1145    kind: impl Into<BuiltinTypeCheckErrorKind>,
1146) -> SerializationError {
1147    mk_typck_err_named(std::any::type_name::<T>(), got, kind)
1148}
1149
1150fn mk_typck_err_named(
1151    name: &'static str,
1152    got: &ColumnType,
1153    kind: impl Into<BuiltinTypeCheckErrorKind>,
1154) -> SerializationError {
1155    SerializationError::new(BuiltinTypeCheckError {
1156        rust_name: name,
1157        got: got.clone().into_owned(),
1158        kind: kind.into(),
1159    })
1160}
1161
1162/// Serialization of one of the built-in types failed.
1163#[derive(Debug, Error, Clone)]
1164#[error("Failed to serialize Rust type {rust_name} into CQL type {got:?}: {kind}")]
1165pub struct BuiltinSerializationError {
1166    /// Name of the Rust type being serialized.
1167    pub rust_name: &'static str,
1168
1169    /// The CQL type that the Rust type was being serialized to.
1170    pub got: ColumnType<'static>,
1171
1172    /// Detailed information about the failure.
1173    pub kind: BuiltinSerializationErrorKind,
1174}
1175
1176/// Creates a [`BuiltinSerializationError`] with the given kind.
1177pub fn mk_ser_err<T: ?Sized>(
1178    got: &ColumnType,
1179    kind: impl Into<BuiltinSerializationErrorKind>,
1180) -> SerializationError {
1181    mk_ser_err_named(std::any::type_name::<T>(), got, kind)
1182}
1183
1184fn mk_ser_err_named(
1185    name: &'static str,
1186    got: &ColumnType,
1187    kind: impl Into<BuiltinSerializationErrorKind>,
1188) -> SerializationError {
1189    SerializationError::new(BuiltinSerializationError {
1190        rust_name: name,
1191        got: got.clone().into_owned(),
1192        kind: kind.into(),
1193    })
1194}
1195
1196/// Describes why type checking some of the built-in types has failed.
1197#[derive(Debug, Clone)]
1198#[non_exhaustive]
1199pub enum BuiltinTypeCheckErrorKind {
1200    /// Expected one from a list of particular types.
1201    MismatchedType {
1202        /// The list of types that the Rust type can serialize as.
1203        expected: &'static [ColumnType<'static>],
1204    },
1205
1206    /// Expected a type that can be empty.
1207    NotEmptyable,
1208
1209    /// A type check failure specific to a CQL set or list.
1210    SetOrListError(SetOrListTypeCheckErrorKind),
1211
1212    /// A type check failure specific to a CQL map.
1213    MapError(MapTypeCheckErrorKind),
1214
1215    /// A type check failure specific to a CQL tuple.
1216    TupleError(TupleTypeCheckErrorKind),
1217
1218    /// A type check failure specific to a CQL UDT.
1219    UdtError(UdtTypeCheckErrorKind),
1220}
1221
1222impl From<SetOrListTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1223    fn from(value: SetOrListTypeCheckErrorKind) -> Self {
1224        BuiltinTypeCheckErrorKind::SetOrListError(value)
1225    }
1226}
1227
1228impl From<MapTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1229    fn from(value: MapTypeCheckErrorKind) -> Self {
1230        BuiltinTypeCheckErrorKind::MapError(value)
1231    }
1232}
1233
1234impl From<TupleTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1235    fn from(value: TupleTypeCheckErrorKind) -> Self {
1236        BuiltinTypeCheckErrorKind::TupleError(value)
1237    }
1238}
1239
1240impl From<UdtTypeCheckErrorKind> for BuiltinTypeCheckErrorKind {
1241    fn from(value: UdtTypeCheckErrorKind) -> Self {
1242        BuiltinTypeCheckErrorKind::UdtError(value)
1243    }
1244}
1245
1246impl Display for BuiltinTypeCheckErrorKind {
1247    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1248        match self {
1249            BuiltinTypeCheckErrorKind::MismatchedType { expected } => {
1250                write!(f, "expected one of the CQL types: {expected:?}")
1251            }
1252            BuiltinTypeCheckErrorKind::NotEmptyable => {
1253                f.write_str("the separate empty representation is not valid for this type")
1254            }
1255            BuiltinTypeCheckErrorKind::SetOrListError(err) => err.fmt(f),
1256            BuiltinTypeCheckErrorKind::MapError(err) => err.fmt(f),
1257            BuiltinTypeCheckErrorKind::TupleError(err) => err.fmt(f),
1258            BuiltinTypeCheckErrorKind::UdtError(err) => err.fmt(f),
1259        }
1260    }
1261}
1262
1263/// Describes why serialization of some of the built-in types has failed.
1264#[derive(Debug, Clone)]
1265#[non_exhaustive]
1266pub enum BuiltinSerializationErrorKind {
1267    /// The size of the Rust value is too large to fit in the CQL serialization
1268    /// format (over i32::MAX bytes).
1269    SizeOverflow,
1270
1271    /// The Rust value is out of range supported by the CQL type.
1272    ValueOverflow,
1273
1274    /// A serialization failure specific to a CQL set or list.
1275    SetOrListError(SetOrListSerializationErrorKind),
1276
1277    /// A serialization failure specific to a CQL set or list.
1278    VectorError(VectorSerializationErrorKind),
1279
1280    /// A serialization failure specific to a CQL map.
1281    MapError(MapSerializationErrorKind),
1282
1283    /// A serialization failure specific to a CQL tuple.
1284    TupleError(TupleSerializationErrorKind),
1285
1286    /// A serialization failure specific to a CQL UDT.
1287    UdtError(UdtSerializationErrorKind),
1288}
1289
1290impl From<SetOrListSerializationErrorKind> for BuiltinSerializationErrorKind {
1291    fn from(value: SetOrListSerializationErrorKind) -> Self {
1292        BuiltinSerializationErrorKind::SetOrListError(value)
1293    }
1294}
1295
1296impl From<VectorSerializationErrorKind> for BuiltinSerializationErrorKind {
1297    fn from(value: VectorSerializationErrorKind) -> Self {
1298        BuiltinSerializationErrorKind::VectorError(value)
1299    }
1300}
1301
1302impl From<MapSerializationErrorKind> for BuiltinSerializationErrorKind {
1303    fn from(value: MapSerializationErrorKind) -> Self {
1304        BuiltinSerializationErrorKind::MapError(value)
1305    }
1306}
1307
1308impl From<TupleSerializationErrorKind> for BuiltinSerializationErrorKind {
1309    fn from(value: TupleSerializationErrorKind) -> Self {
1310        BuiltinSerializationErrorKind::TupleError(value)
1311    }
1312}
1313
1314impl From<UdtSerializationErrorKind> for BuiltinSerializationErrorKind {
1315    fn from(value: UdtSerializationErrorKind) -> Self {
1316        BuiltinSerializationErrorKind::UdtError(value)
1317    }
1318}
1319
1320impl Display for BuiltinSerializationErrorKind {
1321    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1322        match self {
1323            BuiltinSerializationErrorKind::SizeOverflow => {
1324                f.write_str("the Rust value is too big to be serialized in the CQL protocol format")
1325            }
1326            BuiltinSerializationErrorKind::ValueOverflow => {
1327                f.write_str("the Rust value is out of range supported by the CQL type")
1328            }
1329            BuiltinSerializationErrorKind::SetOrListError(err) => err.fmt(f),
1330            BuiltinSerializationErrorKind::VectorError(err) => err.fmt(f),
1331            BuiltinSerializationErrorKind::MapError(err) => err.fmt(f),
1332            BuiltinSerializationErrorKind::TupleError(err) => err.fmt(f),
1333            BuiltinSerializationErrorKind::UdtError(err) => err.fmt(f),
1334        }
1335    }
1336}
1337
1338/// Describes why type checking of a map type failed.
1339#[derive(Debug, Clone)]
1340#[non_exhaustive]
1341pub enum MapTypeCheckErrorKind {
1342    /// The CQL type is not a map.
1343    NotMap,
1344}
1345
1346impl Display for MapTypeCheckErrorKind {
1347    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1348        match self {
1349            MapTypeCheckErrorKind::NotMap => f.write_str(
1350                "the CQL type the Rust type was attempted to be type checked against was not a map",
1351            ),
1352        }
1353    }
1354}
1355
1356/// Describes why serialization of a map type failed.
1357#[derive(Debug, Clone)]
1358#[non_exhaustive]
1359pub enum MapSerializationErrorKind {
1360    /// The many contains too many items, exceeding the protocol limit (i32::MAX).
1361    TooManyElements,
1362
1363    /// One of the keys in the map failed to serialize.
1364    KeySerializationFailed(SerializationError),
1365
1366    /// One of the values in the map failed to serialize.
1367    ValueSerializationFailed(SerializationError),
1368}
1369
1370impl Display for MapSerializationErrorKind {
1371    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1372        match self {
1373            MapSerializationErrorKind::TooManyElements => {
1374                f.write_str("the map contains too many elements to fit in CQL representation")
1375            }
1376            MapSerializationErrorKind::KeySerializationFailed(err) => {
1377                write!(f, "failed to serialize one of the keys: {err}")
1378            }
1379            MapSerializationErrorKind::ValueSerializationFailed(err) => {
1380                write!(f, "failed to serialize one of the values: {err}")
1381            }
1382        }
1383    }
1384}
1385
1386/// Describes why type checking of a set or list type failed.
1387#[derive(Debug, Clone)]
1388#[non_exhaustive]
1389pub enum SetOrListTypeCheckErrorKind {
1390    /// The CQL type is neither a set, nor a list, nor a vector.
1391    NotSetOrList,
1392}
1393
1394impl Display for SetOrListTypeCheckErrorKind {
1395    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1396        match self {
1397            SetOrListTypeCheckErrorKind::NotSetOrList => {
1398                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")
1399            }
1400        }
1401    }
1402}
1403
1404/// Describes why serialization of a set or list type failed.
1405#[derive(Debug, Clone)]
1406#[non_exhaustive]
1407pub enum SetOrListSerializationErrorKind {
1408    /// The set/list contains too many items, exceeding the protocol limit (i32::MAX).
1409    TooManyElements,
1410
1411    /// One of the elements of the set/list failed to serialize.
1412    ElementSerializationFailed(SerializationError),
1413}
1414
1415impl Display for SetOrListSerializationErrorKind {
1416    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1417        match self {
1418            SetOrListSerializationErrorKind::TooManyElements => f.write_str(
1419                "the collection contains too many elements to fit in CQL representation",
1420            ),
1421            SetOrListSerializationErrorKind::ElementSerializationFailed(err) => {
1422                write!(f, "failed to serialize one of the elements: {err}")
1423            }
1424        }
1425    }
1426}
1427
1428/// Describes why serialization of a vector type failed.
1429#[derive(Error, Debug, Clone)]
1430#[non_exhaustive]
1431pub enum VectorSerializationErrorKind {
1432    /// The number of elements in the serialized collection does not match
1433    /// the number of vector dimensions
1434    #[error(
1435        "number of vector elements ({0}) does not match the number of declared dimensions ({1})"
1436    )]
1437    InvalidNumberOfElements(usize, u16),
1438
1439    /// One of the elements of the vector failed to serialize.
1440    #[error("failed to serialize one of the elements: {0}")]
1441    ElementSerializationFailed(SerializationError),
1442}
1443
1444/// Describes why type checking of a tuple failed.
1445#[derive(Debug, Clone)]
1446#[non_exhaustive]
1447pub enum TupleTypeCheckErrorKind {
1448    /// The CQL type is not a tuple.
1449    NotTuple,
1450
1451    /// The tuple has the wrong element count.
1452    ///
1453    /// Note that it is allowed to write a Rust tuple with less elements
1454    /// than the corresponding CQL type, but not more. The additional, unknown
1455    /// elements will be set to null.
1456    WrongElementCount {
1457        /// The number of elements that the Rust tuple has.
1458        rust_type_el_count: usize,
1459
1460        /// The number of elements that the CQL tuple type has.
1461        cql_type_el_count: usize,
1462    },
1463}
1464
1465impl Display for TupleTypeCheckErrorKind {
1466    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1467        match self {
1468            TupleTypeCheckErrorKind::NotTuple => f.write_str(
1469                "the CQL type the Rust type was attempted to be type checked against is not a tuple"
1470            ),
1471            TupleTypeCheckErrorKind::WrongElementCount { rust_type_el_count, cql_type_el_count } => write!(
1472                f,
1473                "wrong tuple element count: CQL type has {cql_type_el_count}, the Rust tuple has {rust_type_el_count}"
1474            ),
1475        }
1476    }
1477}
1478
1479/// Describes why serialize of a tuple failed.
1480#[derive(Debug, Clone)]
1481#[non_exhaustive]
1482pub enum TupleSerializationErrorKind {
1483    /// One of the tuple elements failed to serialize.
1484    ElementSerializationFailed {
1485        /// Index of the tuple element that failed to serialize.
1486        index: usize,
1487
1488        /// The error that caused the tuple field serialization to fail.
1489        err: SerializationError,
1490    },
1491}
1492
1493impl Display for TupleSerializationErrorKind {
1494    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1495        match self {
1496            TupleSerializationErrorKind::ElementSerializationFailed { index, err } => {
1497                write!(f, "element no. {index} failed to serialize: {err}")
1498            }
1499        }
1500    }
1501}
1502
1503/// Describes why type checking of a user defined type failed.
1504#[derive(Debug, Clone)]
1505#[non_exhaustive]
1506pub enum UdtTypeCheckErrorKind {
1507    /// The CQL type is not a user defined type.
1508    NotUdt,
1509
1510    /// The name of the UDT being serialized to does not match.
1511    NameMismatch {
1512        /// Keyspace in which the UDT was defined.
1513        keyspace: String,
1514
1515        /// Name of the UDT.
1516        type_name: String,
1517    },
1518
1519    /// The Rust data does not have a field that is required in the CQL UDT type.
1520    ValueMissingForUdtField {
1521        /// Name of field that the CQL UDT requires but is missing in the Rust struct.
1522        field_name: String,
1523    },
1524
1525    /// The Rust data contains a field that is not present in the UDT.
1526    NoSuchFieldInUdt {
1527        /// Name of the Rust struct field that is missing in the UDT.
1528        field_name: String,
1529    },
1530
1531    /// A different field name was expected at given position.
1532    FieldNameMismatch {
1533        /// The name of the Rust field.
1534        rust_field_name: String,
1535
1536        /// The name of the CQL UDT field.
1537        db_field_name: String,
1538    },
1539}
1540
1541impl Display for UdtTypeCheckErrorKind {
1542    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1543        match self {
1544            UdtTypeCheckErrorKind::NotUdt => f.write_str(
1545                "the CQL type the Rust type was attempted to be type checked against is not a UDT",
1546            ),
1547            UdtTypeCheckErrorKind::NameMismatch {
1548                keyspace,
1549                type_name,
1550            } => write!(
1551                f,
1552                "the Rust UDT name does not match the actual CQL UDT name ({keyspace}.{type_name})"
1553            ),
1554            UdtTypeCheckErrorKind::ValueMissingForUdtField { field_name } => {
1555                write!(
1556                    f,
1557                    "the field {field_name} is missing in the Rust data but is required by the CQL UDT type"
1558                )
1559            }
1560            UdtTypeCheckErrorKind::NoSuchFieldInUdt { field_name } => write!(
1561                f,
1562                "the field {field_name} that is present in the Rust data is not present in the CQL type"
1563            ),
1564            UdtTypeCheckErrorKind::FieldNameMismatch {
1565                rust_field_name,
1566                db_field_name,
1567            } => write!(
1568                f,
1569                "expected field with name {db_field_name} at given position, but the Rust field name is {rust_field_name}"
1570            ),
1571        }
1572    }
1573}
1574
1575/// Describes why serialization of a user defined type failed.
1576#[derive(Debug, Clone)]
1577#[non_exhaustive]
1578pub enum UdtSerializationErrorKind {
1579    /// One of the fields failed to serialize.
1580    FieldSerializationFailed {
1581        /// Name of the field which failed to serialize.
1582        field_name: String,
1583
1584        /// The error that caused the UDT field serialization to fail.
1585        err: SerializationError,
1586    },
1587}
1588
1589impl Display for UdtSerializationErrorKind {
1590    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1591        match self {
1592            UdtSerializationErrorKind::FieldSerializationFailed { field_name, err } => {
1593                write!(f, "field {field_name} failed to serialize: {err}")
1594            }
1595        }
1596    }
1597}
1598
1599#[cfg(test)]
1600#[path = "value_tests.rs"]
1601pub(crate) mod tests;