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