1use std::net::IpAddr;
5use std::result::Result as StdResult;
6
7use thiserror::Error;
8use uuid::Uuid;
9
10use crate::deserialize::value::DeserializeValue;
11use crate::deserialize::value::{
12 mk_deser_err, BuiltinDeserializationErrorKind, MapIterator, UdtIterator, VectorIterator,
13};
14use crate::deserialize::DeserializationError;
15use crate::deserialize::FrameSlice;
16use crate::frame::response::result::{CollectionType, ColumnType};
17use crate::frame::types;
18use crate::utils::safe_format::IteratorSafeFormatExt;
19
20#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
25#[error(
26 "Conversion between CQL type and another type is not possible because\
27 value of one of them is too large to fit in the other"
28)]
29pub struct ValueOverflow;
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
33pub struct Unset;
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
37pub struct Counter(pub i64);
38
39#[derive(Debug, Clone, Copy, Default)]
41pub enum MaybeUnset<V> {
42 #[default]
44 Unset,
45 Set(V),
47}
48
49impl<V> MaybeUnset<V> {
50 #[inline]
52 pub fn from_option(opt: Option<V>) -> Self {
53 match opt {
54 Some(v) => Self::Set(v),
55 None => Self::Unset,
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy, Eq)]
65pub struct CqlTimeuuid(Uuid);
66
67impl CqlTimeuuid {
69 pub fn nil() -> Self {
72 Self(Uuid::nil())
73 }
74
75 pub fn as_bytes(&self) -> &[u8; 16] {
78 self.0.as_bytes()
79 }
80
81 pub fn as_u128(&self) -> u128 {
84 self.0.as_u128()
85 }
86
87 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
90 self.0.as_fields()
91 }
92
93 pub fn as_u64_pair(&self) -> (u64, u64) {
96 self.0.as_u64_pair()
97 }
98
99 pub fn from_slice(b: &[u8]) -> Result<Self, uuid::Error> {
102 Ok(Self(Uuid::from_slice(b)?))
103 }
104
105 pub fn from_slice_le(b: &[u8]) -> Result<Self, uuid::Error> {
108 Ok(Self(Uuid::from_slice_le(b)?))
109 }
110
111 pub fn from_bytes(bytes: [u8; 16]) -> Self {
114 Self(Uuid::from_bytes(bytes))
115 }
116
117 pub fn from_bytes_le(bytes: [u8; 16]) -> Self {
120 Self(Uuid::from_bytes_le(bytes))
121 }
122
123 pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
126 Self(Uuid::from_fields(d1, d2, d3, d4))
127 }
128
129 pub fn from_fields_le(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
132 Self(Uuid::from_fields_le(d1, d2, d3, d4))
133 }
134
135 pub fn from_u128(v: u128) -> Self {
138 Self(Uuid::from_u128(v))
139 }
140
141 pub fn from_u128_le(v: u128) -> Self {
144 Self(Uuid::from_u128_le(v))
145 }
146
147 pub fn from_u64_pair(high_bits: u64, low_bits: u64) -> Self {
150 Self(Uuid::from_u64_pair(high_bits, low_bits))
151 }
152}
153
154impl CqlTimeuuid {
155 fn msb(&self) -> u64 {
157 let bytes = self.0.as_bytes();
161 u64::from_be_bytes([
162 bytes[6] & 0x0f,
163 bytes[7],
164 bytes[4],
165 bytes[5],
166 bytes[0],
167 bytes[1],
168 bytes[2],
169 bytes[3],
170 ])
171 }
172
173 fn lsb(&self) -> u64 {
174 let bytes = self.0.as_bytes();
175 u64::from_be_bytes([
176 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
177 ])
178 }
179
180 fn lsb_signed(&self) -> u64 {
181 self.lsb() ^ 0x8080808080808080
182 }
183}
184
185impl std::str::FromStr for CqlTimeuuid {
186 type Err = uuid::Error;
187
188 fn from_str(s: &str) -> Result<Self, Self::Err> {
189 Ok(Self(Uuid::from_str(s)?))
190 }
191}
192
193impl std::fmt::Display for CqlTimeuuid {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 write!(f, "{}", self.0)
196 }
197}
198
199impl AsRef<Uuid> for CqlTimeuuid {
200 fn as_ref(&self) -> &Uuid {
201 &self.0
202 }
203}
204
205impl From<CqlTimeuuid> for Uuid {
206 fn from(value: CqlTimeuuid) -> Self {
207 value.0
208 }
209}
210
211impl From<Uuid> for CqlTimeuuid {
212 fn from(value: Uuid) -> Self {
213 Self(value)
214 }
215}
216
217impl Ord for CqlTimeuuid {
225 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
226 let mut res = self.msb().cmp(&other.msb());
227 if let std::cmp::Ordering::Equal = res {
228 res = self.lsb_signed().cmp(&other.lsb_signed());
229 }
230 res
231 }
232}
233
234impl PartialOrd for CqlTimeuuid {
235 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
236 Some(self.cmp(other))
237 }
238}
239
240impl PartialEq for CqlTimeuuid {
241 fn eq(&self, other: &Self) -> bool {
242 self.cmp(other) == std::cmp::Ordering::Equal
243 }
244}
245
246impl std::hash::Hash for CqlTimeuuid {
247 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
248 self.lsb_signed().hash(state);
249 self.msb().hash(state);
250 }
251}
252
253#[derive(Clone, Eq, Debug)]
281pub struct CqlVarint(Vec<u8>);
282
283#[derive(Clone, Eq, Debug)]
288pub struct CqlVarintBorrowed<'b>(&'b [u8]);
289
290impl CqlVarint {
292 pub fn from_signed_bytes_be(digits: Vec<u8>) -> Self {
297 Self(digits)
298 }
299
300 pub fn from_signed_bytes_be_slice(digits: &[u8]) -> Self {
305 Self::from_signed_bytes_be(digits.to_vec())
306 }
307}
308
309impl<'b> CqlVarintBorrowed<'b> {
311 pub fn from_signed_bytes_be_slice(digits: &'b [u8]) -> Self {
316 Self(digits)
317 }
318}
319
320impl CqlVarint {
322 pub fn into_signed_bytes_be(self) -> Vec<u8> {
325 self.0
326 }
327
328 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
331 &self.0
332 }
333}
334
335impl CqlVarintBorrowed<'_> {
337 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
340 self.0
341 }
342}
343
344trait AsVarintSlice {
347 fn as_slice(&self) -> &[u8];
348}
349impl AsVarintSlice for CqlVarint {
350 fn as_slice(&self) -> &[u8] {
351 self.as_signed_bytes_be_slice()
352 }
353}
354impl AsVarintSlice for CqlVarintBorrowed<'_> {
355 fn as_slice(&self) -> &[u8] {
356 self.as_signed_bytes_be_slice()
357 }
358}
359
360trait AsNormalizedVarintSlice {
363 fn as_normalized_slice(&self) -> &[u8];
364}
365impl<V: AsVarintSlice> AsNormalizedVarintSlice for V {
366 fn as_normalized_slice(&self) -> &[u8] {
367 let digits = self.as_slice();
368 if digits.is_empty() {
369 return &[0];
372 }
373
374 let non_zero_position = match digits.iter().position(|b| *b != 0) {
375 Some(pos) => pos,
376 None => {
377 return &[0];
379 }
380 };
381
382 if non_zero_position > 0 {
383 let zeros_to_remove = if digits[non_zero_position] > 0x7f {
386 non_zero_position - 1
389 } else {
390 non_zero_position
392 };
393 return &digits[zeros_to_remove..];
394 }
395
396 digits
398 }
399}
400
401impl PartialEq for CqlVarint {
415 fn eq(&self, other: &Self) -> bool {
416 self.as_normalized_slice() == other.as_normalized_slice()
417 }
418}
419
420impl std::hash::Hash for CqlVarint {
422 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
423 self.as_normalized_slice().hash(state)
424 }
425}
426
427impl PartialEq for CqlVarintBorrowed<'_> {
441 fn eq(&self, other: &Self) -> bool {
442 self.as_normalized_slice() == other.as_normalized_slice()
443 }
444}
445
446impl std::hash::Hash for CqlVarintBorrowed<'_> {
448 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
449 self.as_normalized_slice().hash(state)
450 }
451}
452
453#[cfg(feature = "num-bigint-03")]
454impl From<num_bigint_03::BigInt> for CqlVarint {
455 fn from(value: num_bigint_03::BigInt) -> Self {
456 Self(value.to_signed_bytes_be())
457 }
458}
459
460#[cfg(feature = "num-bigint-03")]
461impl From<CqlVarint> for num_bigint_03::BigInt {
462 fn from(val: CqlVarint) -> Self {
463 num_bigint_03::BigInt::from_signed_bytes_be(&val.0)
464 }
465}
466
467#[cfg(feature = "num-bigint-03")]
468impl From<CqlVarintBorrowed<'_>> for num_bigint_03::BigInt {
469 fn from(val: CqlVarintBorrowed<'_>) -> Self {
470 num_bigint_03::BigInt::from_signed_bytes_be(val.0)
471 }
472}
473
474#[cfg(feature = "num-bigint-04")]
475impl From<num_bigint_04::BigInt> for CqlVarint {
476 fn from(value: num_bigint_04::BigInt) -> Self {
477 Self(value.to_signed_bytes_be())
478 }
479}
480
481#[cfg(feature = "num-bigint-04")]
482impl From<CqlVarint> for num_bigint_04::BigInt {
483 fn from(val: CqlVarint) -> Self {
484 num_bigint_04::BigInt::from_signed_bytes_be(&val.0)
485 }
486}
487
488#[cfg(feature = "num-bigint-04")]
489impl From<CqlVarintBorrowed<'_>> for num_bigint_04::BigInt {
490 fn from(val: CqlVarintBorrowed<'_>) -> Self {
491 num_bigint_04::BigInt::from_signed_bytes_be(val.0)
492 }
493}
494
495#[derive(Clone, PartialEq, Eq, Debug)]
515pub struct CqlDecimal {
516 int_val: CqlVarint,
517 scale: i32,
518}
519
520#[derive(Clone, PartialEq, Eq, Debug)]
529pub struct CqlDecimalBorrowed<'b> {
530 int_val: CqlVarintBorrowed<'b>,
531 scale: i32,
532}
533
534impl CqlDecimal {
536 pub fn from_signed_be_bytes_and_exponent(bytes: Vec<u8>, scale: i32) -> Self {
541 Self {
542 int_val: CqlVarint::from_signed_bytes_be(bytes),
543 scale,
544 }
545 }
546
547 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &[u8], scale: i32) -> Self {
552 Self::from_signed_be_bytes_and_exponent(bytes.to_vec(), scale)
553 }
554}
555
556impl<'b> CqlDecimalBorrowed<'b> {
558 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &'b [u8], scale: i32) -> Self {
563 Self {
564 int_val: CqlVarintBorrowed::from_signed_bytes_be_slice(bytes),
565 scale,
566 }
567 }
568}
569
570impl CqlDecimal {
572 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
575 (self.int_val.as_signed_bytes_be_slice(), self.scale)
576 }
577
578 pub fn into_signed_be_bytes_and_exponent(self) -> (Vec<u8>, i32) {
581 (self.int_val.into_signed_bytes_be(), self.scale)
582 }
583}
584
585impl CqlDecimalBorrowed<'_> {
587 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
590 (self.int_val.as_signed_bytes_be_slice(), self.scale)
591 }
592}
593
594#[cfg(feature = "bigdecimal-04")]
595impl From<CqlDecimal> for bigdecimal_04::BigDecimal {
596 fn from(value: CqlDecimal) -> Self {
597 Self::from((
598 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
599 value.int_val.as_signed_bytes_be_slice(),
600 ),
601 value.scale as i64,
602 ))
603 }
604}
605
606#[cfg(feature = "bigdecimal-04")]
607impl From<CqlDecimalBorrowed<'_>> for bigdecimal_04::BigDecimal {
608 fn from(value: CqlDecimalBorrowed) -> Self {
609 Self::from((
610 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
611 value.int_val.as_signed_bytes_be_slice(),
612 ),
613 value.scale as i64,
614 ))
615 }
616}
617
618#[cfg(feature = "bigdecimal-04")]
619impl TryFrom<bigdecimal_04::BigDecimal> for CqlDecimal {
620 type Error = <i64 as TryInto<i32>>::Error;
621
622 fn try_from(value: bigdecimal_04::BigDecimal) -> Result<Self, Self::Error> {
623 let (bigint, scale) = value.into_bigint_and_exponent();
624 let bytes = bigint.to_signed_bytes_be();
625 Ok(Self::from_signed_be_bytes_and_exponent(
626 bytes,
627 scale.try_into()?,
628 ))
629 }
630}
631
632#[derive(Clone, Copy, PartialEq, Eq, Debug)]
636pub struct CqlDate(pub u32);
637
638#[derive(Clone, Copy, PartialEq, Eq, Debug)]
642pub struct CqlTimestamp(pub i64);
643
644#[derive(Clone, Copy, PartialEq, Eq, Debug)]
648pub struct CqlTime(pub i64);
649
650impl CqlDate {
651 fn try_to_chrono_04_naive_date(&self) -> Result<chrono_04::NaiveDate, ValueOverflow> {
652 let days_since_unix_epoch = self.0 as i64 - (1 << 31);
653
654 let duration_since_unix_epoch =
657 chrono_04::Duration::try_days(days_since_unix_epoch).unwrap();
658
659 chrono_04::NaiveDate::from_yo_opt(1970, 1)
660 .unwrap()
661 .checked_add_signed(duration_since_unix_epoch)
662 .ok_or(ValueOverflow)
663 }
664}
665
666#[cfg(feature = "chrono-04")]
667impl From<chrono_04::NaiveDate> for CqlDate {
668 fn from(value: chrono_04::NaiveDate) -> Self {
669 let unix_epoch = chrono_04::NaiveDate::from_yo_opt(1970, 1).unwrap();
670
671 let days = ((1 << 31) + value.signed_duration_since(unix_epoch).num_days()) as u32;
674
675 Self(days)
676 }
677}
678
679#[cfg(feature = "chrono-04")]
680impl TryInto<chrono_04::NaiveDate> for CqlDate {
681 type Error = ValueOverflow;
682
683 fn try_into(self) -> Result<chrono_04::NaiveDate, Self::Error> {
684 self.try_to_chrono_04_naive_date()
685 }
686}
687
688impl CqlTimestamp {
689 fn try_to_chrono_04_datetime_utc(
690 &self,
691 ) -> Result<chrono_04::DateTime<chrono_04::Utc>, ValueOverflow> {
692 use chrono_04::TimeZone;
693 match chrono_04::Utc.timestamp_millis_opt(self.0) {
694 chrono_04::LocalResult::Single(datetime) => Ok(datetime),
695 _ => Err(ValueOverflow),
696 }
697 }
698}
699
700#[cfg(feature = "chrono-04")]
701impl From<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
702 fn from(value: chrono_04::DateTime<chrono_04::Utc>) -> Self {
703 Self(value.timestamp_millis())
704 }
705}
706
707#[cfg(feature = "chrono-04")]
708impl TryInto<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
709 type Error = ValueOverflow;
710
711 fn try_into(self) -> Result<chrono_04::DateTime<chrono_04::Utc>, Self::Error> {
712 self.try_to_chrono_04_datetime_utc()
713 }
714}
715
716#[cfg(feature = "chrono-04")]
717impl TryFrom<chrono_04::NaiveTime> for CqlTime {
718 type Error = ValueOverflow;
719
720 fn try_from(value: chrono_04::NaiveTime) -> Result<Self, Self::Error> {
721 let nanos = value
722 .signed_duration_since(chrono_04::NaiveTime::MIN)
723 .num_nanoseconds()
724 .unwrap();
725
726 if nanos <= 86399999999999 {
728 Ok(Self(nanos))
729 } else {
730 Err(ValueOverflow)
731 }
732 }
733}
734
735#[cfg(feature = "chrono-04")]
736impl TryInto<chrono_04::NaiveTime> for CqlTime {
737 type Error = ValueOverflow;
738
739 fn try_into(self) -> Result<chrono_04::NaiveTime, Self::Error> {
740 let secs = (self.0 / 1_000_000_000)
741 .try_into()
742 .map_err(|_| ValueOverflow)?;
743 let nanos = (self.0 % 1_000_000_000)
744 .try_into()
745 .map_err(|_| ValueOverflow)?;
746 chrono_04::NaiveTime::from_num_seconds_from_midnight_opt(secs, nanos).ok_or(ValueOverflow)
747 }
748}
749
750#[cfg(feature = "time-03")]
751impl From<time_03::Date> for CqlDate {
752 fn from(value: time_03::Date) -> Self {
753 const JULIAN_DAY_OFFSET: i64 =
754 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
755
756 const _: () = assert!(
758 time_03::Date::MAX.to_julian_day() as i64 + JULIAN_DAY_OFFSET < u32::MAX as i64
759 );
760 const _: () = assert!(
761 time_03::Date::MIN.to_julian_day() as i64 + JULIAN_DAY_OFFSET > u32::MIN as i64
762 );
763
764 let days = value.to_julian_day() as i64 + JULIAN_DAY_OFFSET;
765
766 Self(days as u32)
767 }
768}
769
770#[cfg(feature = "time-03")]
771impl TryInto<time_03::Date> for CqlDate {
772 type Error = ValueOverflow;
773
774 fn try_into(self) -> Result<time_03::Date, Self::Error> {
775 const JULIAN_DAY_OFFSET: i64 =
776 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
777
778 let julian_days = (self.0 as i64 - JULIAN_DAY_OFFSET)
779 .try_into()
780 .map_err(|_| ValueOverflow)?;
781
782 time_03::Date::from_julian_day(julian_days).map_err(|_| ValueOverflow)
783 }
784}
785
786#[cfg(feature = "time-03")]
787impl From<time_03::OffsetDateTime> for CqlTimestamp {
788 fn from(value: time_03::OffsetDateTime) -> Self {
789 const _: () = assert!(
792 time_03::PrimitiveDateTime::MAX
793 .assume_utc()
794 .unix_timestamp_nanos()
795 / 1_000_000
797 < i64::MAX as i128
798 );
799 const _: () = assert!(
800 time_03::PrimitiveDateTime::MIN
801 .assume_utc()
802 .unix_timestamp_nanos()
803 / 1_000_000
804 > i64::MIN as i128
805 );
806
807 Self(value.unix_timestamp() * 1000 + value.millisecond() as i64)
809 }
810}
811
812#[cfg(feature = "time-03")]
813impl TryInto<time_03::OffsetDateTime> for CqlTimestamp {
814 type Error = ValueOverflow;
815
816 fn try_into(self) -> Result<time_03::OffsetDateTime, Self::Error> {
817 time_03::OffsetDateTime::from_unix_timestamp_nanos(self.0 as i128 * 1_000_000)
818 .map_err(|_| ValueOverflow)
819 }
820}
821
822#[cfg(feature = "time-03")]
823impl From<time_03::Time> for CqlTime {
824 fn from(value: time_03::Time) -> Self {
825 let (h, m, s, n) = value.as_hms_nano();
826
827 let nanos = (h as i64 * 3600 + m as i64 * 60 + s as i64) * 1_000_000_000 + n as i64;
829
830 Self(nanos)
831 }
832}
833
834#[cfg(feature = "time-03")]
835impl TryInto<time_03::Time> for CqlTime {
836 type Error = ValueOverflow;
837
838 fn try_into(self) -> Result<time_03::Time, Self::Error> {
839 let h = self.0 / 3_600_000_000_000;
840 let m = self.0 / 60_000_000_000 % 60;
841 let s = self.0 / 1_000_000_000 % 60;
842 let n = self.0 % 1_000_000_000;
843
844 time_03::Time::from_hms_nano(
845 h.try_into().map_err(|_| ValueOverflow)?,
846 m as u8,
847 s as u8,
848 n as u32,
849 )
850 .map_err(|_| ValueOverflow)
851 }
852}
853
854#[derive(Clone, Debug, Copy, PartialEq, Eq)]
856pub struct CqlDuration {
857 pub months: i32,
859 pub days: i32,
861 pub nanoseconds: i64,
863}
864
865#[derive(Clone, Debug, PartialEq)]
871#[non_exhaustive]
872pub enum CqlValue {
873 Ascii(String),
875 Boolean(bool),
877 Blob(Vec<u8>),
879 Counter(Counter),
881 Decimal(CqlDecimal),
883 Date(CqlDate),
886 Double(f64),
888 Duration(CqlDuration),
890 Empty,
892 Float(f32),
894 Int(i32),
896 BigInt(i64),
898 Text(String),
900 Timestamp(CqlTimestamp),
902 Inet(IpAddr),
904 List(Vec<CqlValue>),
906 Map(Vec<(CqlValue, CqlValue)>),
909 Set(Vec<CqlValue>),
911 UserDefinedType {
915 keyspace: String,
917 name: String,
919 fields: Vec<(String, Option<CqlValue>)>,
921 },
922 SmallInt(i16),
924 TinyInt(i8),
926 Time(CqlTime),
928 Timeuuid(CqlTimeuuid),
930 Tuple(Vec<Option<CqlValue>>),
933 Uuid(Uuid),
935 Varint(CqlVarint),
937 Vector(Vec<CqlValue>),
940}
941
942impl CqlValue {
943 pub fn as_ascii(&self) -> Option<&String> {
945 match self {
946 Self::Ascii(s) => Some(s),
947 _ => None,
948 }
949 }
950
951 pub fn as_cql_date(&self) -> Option<CqlDate> {
953 match self {
954 Self::Date(d) => Some(*d),
955 _ => None,
956 }
957 }
958
959 #[cfg(test)]
961 #[cfg(feature = "chrono-04")]
962 pub(crate) fn as_naive_date_04(&self) -> Option<chrono_04::NaiveDate> {
963 self.as_cql_date().and_then(|date| date.try_into().ok())
964 }
965
966 #[cfg(test)]
968 #[cfg(feature = "time-03")]
969 pub(crate) fn as_date_03(&self) -> Option<time_03::Date> {
970 self.as_cql_date().and_then(|date| date.try_into().ok())
971 }
972
973 pub fn as_cql_timestamp(&self) -> Option<CqlTimestamp> {
975 match self {
976 Self::Timestamp(i) => Some(*i),
977 _ => None,
978 }
979 }
980
981 #[cfg(test)]
983 #[cfg(feature = "chrono-04")]
984 pub(crate) fn as_datetime_04(&self) -> Option<chrono_04::DateTime<chrono_04::Utc>> {
985 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
986 }
987
988 #[cfg(test)]
990 #[cfg(feature = "time-03")]
991 pub(crate) fn as_offset_date_time_03(&self) -> Option<time_03::OffsetDateTime> {
992 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
993 }
994
995 pub fn as_cql_time(&self) -> Option<CqlTime> {
997 match self {
998 Self::Time(i) => Some(*i),
999 _ => None,
1000 }
1001 }
1002
1003 #[cfg(test)]
1005 #[cfg(feature = "chrono-04")]
1006 pub(crate) fn as_naive_time_04(&self) -> Option<chrono_04::NaiveTime> {
1007 self.as_cql_time().and_then(|ts| ts.try_into().ok())
1008 }
1009
1010 #[cfg(test)]
1012 #[cfg(feature = "time-03")]
1013 pub(crate) fn as_time_03(&self) -> Option<time_03::Time> {
1014 self.as_cql_time().and_then(|ts| ts.try_into().ok())
1015 }
1016
1017 pub fn as_cql_duration(&self) -> Option<CqlDuration> {
1019 match self {
1020 Self::Duration(i) => Some(*i),
1021 _ => None,
1022 }
1023 }
1024
1025 pub fn as_counter(&self) -> Option<Counter> {
1027 match self {
1028 Self::Counter(i) => Some(*i),
1029 _ => None,
1030 }
1031 }
1032
1033 pub fn as_boolean(&self) -> Option<bool> {
1035 match self {
1036 Self::Boolean(i) => Some(*i),
1037 _ => None,
1038 }
1039 }
1040
1041 pub fn as_double(&self) -> Option<f64> {
1043 match self {
1044 Self::Double(d) => Some(*d),
1045 _ => None,
1046 }
1047 }
1048
1049 pub fn as_uuid(&self) -> Option<Uuid> {
1051 match self {
1052 Self::Uuid(u) => Some(*u),
1053 _ => None,
1054 }
1055 }
1056
1057 pub fn as_float(&self) -> Option<f32> {
1059 match self {
1060 Self::Float(f) => Some(*f),
1061 _ => None,
1062 }
1063 }
1064
1065 pub fn as_int(&self) -> Option<i32> {
1067 match self {
1068 Self::Int(i) => Some(*i),
1069 _ => None,
1070 }
1071 }
1072
1073 pub fn as_bigint(&self) -> Option<i64> {
1075 match self {
1076 Self::BigInt(i) => Some(*i),
1077 _ => None,
1078 }
1079 }
1080
1081 pub fn as_tinyint(&self) -> Option<i8> {
1083 match self {
1084 Self::TinyInt(i) => Some(*i),
1085 _ => None,
1086 }
1087 }
1088
1089 pub fn as_smallint(&self) -> Option<i16> {
1091 match self {
1092 Self::SmallInt(i) => Some(*i),
1093 _ => None,
1094 }
1095 }
1096
1097 pub fn as_blob(&self) -> Option<&Vec<u8>> {
1099 match self {
1100 Self::Blob(v) => Some(v),
1101 _ => None,
1102 }
1103 }
1104
1105 pub fn as_text(&self) -> Option<&String> {
1107 match self {
1108 Self::Text(s) => Some(s),
1109 _ => None,
1110 }
1111 }
1112
1113 pub fn as_timeuuid(&self) -> Option<CqlTimeuuid> {
1115 match self {
1116 Self::Timeuuid(u) => Some(*u),
1117 _ => None,
1118 }
1119 }
1120
1121 pub fn into_string(self) -> Option<String> {
1123 match self {
1124 Self::Ascii(s) => Some(s),
1125 Self::Text(s) => Some(s),
1126 _ => None,
1127 }
1128 }
1129
1130 pub fn into_blob(self) -> Option<Vec<u8>> {
1132 match self {
1133 Self::Blob(b) => Some(b),
1134 _ => None,
1135 }
1136 }
1137
1138 pub fn as_inet(&self) -> Option<IpAddr> {
1140 match self {
1141 Self::Inet(a) => Some(*a),
1142 _ => None,
1143 }
1144 }
1145
1146 pub fn as_list(&self) -> Option<&Vec<CqlValue>> {
1148 match self {
1149 Self::List(s) => Some(s),
1150 _ => None,
1151 }
1152 }
1153
1154 pub fn as_set(&self) -> Option<&Vec<CqlValue>> {
1156 match self {
1157 Self::Set(s) => Some(s),
1158 _ => None,
1159 }
1160 }
1161
1162 pub fn as_map(&self) -> Option<&Vec<(CqlValue, CqlValue)>> {
1165 match self {
1166 Self::Map(s) => Some(s),
1167 _ => None,
1168 }
1169 }
1170
1171 pub fn as_udt(&self) -> Option<&Vec<(String, Option<CqlValue>)>> {
1175 match self {
1176 Self::UserDefinedType { fields, .. } => Some(fields),
1177 _ => None,
1178 }
1179 }
1180
1181 pub fn into_vec(self) -> Option<Vec<CqlValue>> {
1183 match self {
1184 Self::List(s) => Some(s),
1185 Self::Set(s) => Some(s),
1186 _ => None,
1187 }
1188 }
1189
1190 pub fn into_pair_vec(self) -> Option<Vec<(CqlValue, CqlValue)>> {
1193 match self {
1194 Self::Map(s) => Some(s),
1195 _ => None,
1196 }
1197 }
1198
1199 pub fn into_udt_pair_vec(self) -> Option<Vec<(String, Option<CqlValue>)>> {
1202 match self {
1203 Self::UserDefinedType { fields, .. } => Some(fields),
1204 _ => None,
1205 }
1206 }
1207
1208 pub fn into_cql_varint(self) -> Option<CqlVarint> {
1210 match self {
1211 Self::Varint(i) => Some(i),
1212 _ => None,
1213 }
1214 }
1215
1216 pub fn into_cql_decimal(self) -> Option<CqlDecimal> {
1218 match self {
1219 Self::Decimal(i) => Some(i),
1220 _ => None,
1221 }
1222 }
1223 }
1225
1226impl std::fmt::Display for CqlValue {
1229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1230 use crate::pretty::{
1231 CqlStringLiteralDisplayer, HexBytes, MaybeNullDisplayer, PairDisplayer,
1232 };
1233
1234 match self {
1235 CqlValue::Ascii(a) => write!(f, "{}", CqlStringLiteralDisplayer(a))?,
1237 CqlValue::Text(t) => write!(f, "{}", CqlStringLiteralDisplayer(t))?,
1238 CqlValue::Blob(b) => write!(f, "0x{:x}", HexBytes(b))?,
1239 CqlValue::Empty => write!(f, "0x")?,
1240 CqlValue::Decimal(d) => {
1241 let (bytes, scale) = d.as_signed_be_bytes_slice_and_exponent();
1242 write!(
1243 f,
1244 "blobAsDecimal(0x{:x}{:x})",
1245 HexBytes(&scale.to_be_bytes()),
1246 HexBytes(bytes)
1247 )?
1248 }
1249 CqlValue::Float(fl) => write!(f, "{fl}")?,
1250 CqlValue::Double(d) => write!(f, "{d}")?,
1251 CqlValue::Boolean(b) => write!(f, "{b}")?,
1252 CqlValue::Int(i) => write!(f, "{i}")?,
1253 CqlValue::BigInt(bi) => write!(f, "{bi}")?,
1254 CqlValue::Inet(i) => write!(f, "'{i}'")?,
1255 CqlValue::SmallInt(si) => write!(f, "{si}")?,
1256 CqlValue::TinyInt(ti) => write!(f, "{ti}")?,
1257 CqlValue::Varint(vi) => write!(
1258 f,
1259 "blobAsVarint(0x{:x})",
1260 HexBytes(vi.as_signed_bytes_be_slice())
1261 )?,
1262 CqlValue::Counter(c) => write!(f, "{}", c.0)?,
1263 CqlValue::Date(d) => {
1264 match d.try_to_chrono_04_naive_date() {
1267 Ok(d) => write!(f, "'{d}'")?,
1268 Err(_) => f.write_str("<date out of representable range>")?,
1269 }
1270 }
1271 CqlValue::Duration(d) => write!(f, "{}mo{}d{}ns", d.months, d.days, d.nanoseconds)?,
1272 CqlValue::Time(CqlTime(t)) => {
1273 write!(
1274 f,
1275 "'{:02}:{:02}:{:02}.{:09}'",
1276 t / 3_600_000_000_000,
1277 t / 60_000_000_000 % 60,
1278 t / 1_000_000_000 % 60,
1279 t % 1_000_000_000,
1280 )?;
1281 }
1282 CqlValue::Timestamp(ts) => match ts.try_to_chrono_04_datetime_utc() {
1283 Ok(d) => write!(f, "{}", d.format("'%Y-%m-%d %H:%M:%S%.3f%z'"))?,
1284 Err(_) => f.write_str("<timestamp out of representable range>")?,
1285 },
1286 CqlValue::Timeuuid(t) => write!(f, "{t}")?,
1287 CqlValue::Uuid(u) => write!(f, "{u}")?,
1288
1289 CqlValue::Tuple(t) => {
1291 f.write_str("(")?;
1292 t.iter()
1293 .map(|x| MaybeNullDisplayer(x.as_ref()))
1294 .safe_format(",")
1295 .fmt(f)?;
1296 f.write_str(")")?;
1297 }
1298 CqlValue::List(v) | CqlValue::Vector(v) => {
1299 f.write_str("[")?;
1300 v.iter().safe_format(",").fmt(f)?;
1301 f.write_str("]")?;
1302 }
1303 CqlValue::Set(v) => {
1304 f.write_str("{")?;
1305 v.iter().safe_format(",").fmt(f)?;
1306 f.write_str("}")?;
1307 }
1308 CqlValue::Map(m) => {
1309 f.write_str("{")?;
1310 m.iter()
1311 .map(|(k, v)| PairDisplayer(k, v))
1312 .safe_format(",")
1313 .fmt(f)?;
1314 f.write_str("}")?;
1315 }
1316 CqlValue::UserDefinedType {
1317 keyspace: _,
1318 name: _,
1319 fields,
1320 } => {
1321 f.write_str("{")?;
1322 fields
1323 .iter()
1324 .map(|(k, v)| PairDisplayer(k, MaybeNullDisplayer(v.as_ref())))
1325 .safe_format(",")
1326 .fmt(f)?;
1327 f.write_str("}")?;
1328 }
1329 }
1330 Ok(())
1331 }
1332}
1333
1334pub fn deser_cql_value(
1336 typ: &ColumnType,
1337 buf: &mut &[u8],
1338) -> StdResult<CqlValue, DeserializationError> {
1339 use crate::frame::response::result::ColumnType::*;
1340 use crate::frame::response::result::NativeType::*;
1341
1342 if buf.is_empty() {
1343 match typ {
1344 Native(Ascii) | Native(Blob) | Native(Text) => {
1345 }
1347 _ => return Ok(CqlValue::Empty),
1348 }
1349 }
1350 let v = Some(FrameSlice::new_borrowed(buf));
1355
1356 Ok(match typ {
1357 Native(Ascii) => {
1358 let s = String::deserialize(typ, v)?;
1359 CqlValue::Ascii(s)
1360 }
1361 Native(Boolean) => {
1362 let b = bool::deserialize(typ, v)?;
1363 CqlValue::Boolean(b)
1364 }
1365 Native(Blob) => {
1366 let b = Vec::<u8>::deserialize(typ, v)?;
1367 CqlValue::Blob(b)
1368 }
1369 Native(Date) => {
1370 let d = CqlDate::deserialize(typ, v)?;
1371 CqlValue::Date(d)
1372 }
1373 Native(Counter) => {
1374 let c = crate::value::Counter::deserialize(typ, v)?;
1375 CqlValue::Counter(c)
1376 }
1377 Native(Decimal) => {
1378 let d = CqlDecimal::deserialize(typ, v)?;
1379 CqlValue::Decimal(d)
1380 }
1381 Native(Double) => {
1382 let d = f64::deserialize(typ, v)?;
1383 CqlValue::Double(d)
1384 }
1385 Native(Float) => {
1386 let f = f32::deserialize(typ, v)?;
1387 CqlValue::Float(f)
1388 }
1389 Native(Int) => {
1390 let i = i32::deserialize(typ, v)?;
1391 CqlValue::Int(i)
1392 }
1393 Native(SmallInt) => {
1394 let si = i16::deserialize(typ, v)?;
1395 CqlValue::SmallInt(si)
1396 }
1397 Native(TinyInt) => {
1398 let ti = i8::deserialize(typ, v)?;
1399 CqlValue::TinyInt(ti)
1400 }
1401 Native(BigInt) => {
1402 let bi = i64::deserialize(typ, v)?;
1403 CqlValue::BigInt(bi)
1404 }
1405 Native(Text) => {
1406 let s = String::deserialize(typ, v)?;
1407 CqlValue::Text(s)
1408 }
1409 Native(Timestamp) => {
1410 let t = CqlTimestamp::deserialize(typ, v)?;
1411 CqlValue::Timestamp(t)
1412 }
1413 Native(Time) => {
1414 let t = CqlTime::deserialize(typ, v)?;
1415 CqlValue::Time(t)
1416 }
1417 Native(Timeuuid) => {
1418 let t = CqlTimeuuid::deserialize(typ, v)?;
1419 CqlValue::Timeuuid(t)
1420 }
1421 Native(Duration) => {
1422 let d = CqlDuration::deserialize(typ, v)?;
1423 CqlValue::Duration(d)
1424 }
1425 Native(Inet) => {
1426 let i = IpAddr::deserialize(typ, v)?;
1427 CqlValue::Inet(i)
1428 }
1429 Native(Uuid) => {
1430 let uuid = uuid::Uuid::deserialize(typ, v)?;
1431 CqlValue::Uuid(uuid)
1432 }
1433 Native(Varint) => {
1434 let vi = CqlVarint::deserialize(typ, v)?;
1435 CqlValue::Varint(vi)
1436 }
1437 Collection {
1438 typ: CollectionType::List(_type_name),
1439 ..
1440 } => {
1441 let l = Vec::<CqlValue>::deserialize(typ, v)?;
1442 CqlValue::List(l)
1443 }
1444 Collection {
1445 typ: CollectionType::Map(_key_type, _value_type),
1446 ..
1447 } => {
1448 let iter = MapIterator::<'_, '_, CqlValue, CqlValue>::deserialize(typ, v)?;
1449 let m: Vec<(CqlValue, CqlValue)> = iter.collect::<StdResult<_, _>>()?;
1450 CqlValue::Map(m)
1451 }
1452 Collection {
1453 typ: CollectionType::Set(_type_name),
1454 ..
1455 } => {
1456 let s = Vec::<CqlValue>::deserialize(typ, v)?;
1457 CqlValue::Set(s)
1458 }
1459 Vector { .. } => {
1460 let iter = VectorIterator::deserialize(typ, v)?;
1461 let v: Vec<CqlValue> = iter.collect::<StdResult<_, _>>()?;
1462 CqlValue::Vector(v)
1463 }
1464 UserDefinedType {
1465 definition: udt, ..
1466 } => {
1467 let iter = UdtIterator::deserialize(typ, v)?;
1468 let fields: Vec<(String, Option<CqlValue>)> = iter
1469 .map(|((col_name, col_type), res)| {
1470 res.and_then(|v| {
1471 let val = Option::<CqlValue>::deserialize(col_type, v.flatten())?;
1472 Ok((col_name.clone().into_owned(), val))
1473 })
1474 })
1475 .collect::<StdResult<_, _>>()?;
1476
1477 CqlValue::UserDefinedType {
1478 keyspace: udt.keyspace.clone().into_owned(),
1479 name: udt.name.clone().into_owned(),
1480 fields,
1481 }
1482 }
1483 Tuple(type_names) => {
1484 let t = type_names
1485 .iter()
1486 .map(|typ| -> StdResult<_, DeserializationError> {
1487 let raw = types::read_bytes_opt(buf).map_err(|e| {
1488 mk_deser_err::<CqlValue>(
1489 typ,
1490 BuiltinDeserializationErrorKind::RawCqlBytesReadError(e),
1491 )
1492 })?;
1493 raw.map(|v| CqlValue::deserialize(typ, Some(FrameSlice::new_borrowed(v))))
1494 .transpose()
1495 })
1496 .collect::<StdResult<_, _>>()?;
1497 CqlValue::Tuple(t)
1498 }
1499 })
1500}
1501
1502#[derive(Debug, Default, PartialEq)]
1513pub struct Row {
1514 pub columns: Vec<Option<CqlValue>>,
1518}
1519
1520#[cfg(test)]
1521mod tests {
1522 use std::str::FromStr as _;
1523
1524 use super::*;
1525
1526 #[test]
1527 fn timeuuid_msb_byte_order() {
1528 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1529
1530 assert_eq!(0x0607040500010203, uuid.msb());
1531 }
1532
1533 #[test]
1534 fn timeuuid_msb_clears_version_bits() {
1535 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1537
1538 assert_eq!(0x0fffffffffffffff, uuid.msb());
1539 }
1540
1541 #[test]
1542 fn timeuuid_lsb_byte_order() {
1543 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1544
1545 assert_eq!(0x08090a0b0c0d0e0f, uuid.lsb());
1546 }
1547
1548 #[test]
1549 fn timeuuid_lsb_modifies_no_bits() {
1550 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1551
1552 assert_eq!(0xffffffffffffffff, uuid.lsb());
1553 }
1554
1555 #[test]
1556 fn timeuuid_nil() {
1557 let uuid = CqlTimeuuid::nil();
1558
1559 assert_eq!(0x0000000000000000, uuid.msb());
1560 assert_eq!(0x0000000000000000, uuid.lsb());
1561 }
1562
1563 #[test]
1564 fn test_cql_value_displayer() {
1565 assert_eq!(format!("{}", CqlValue::Boolean(true)), "true");
1566 assert_eq!(format!("{}", CqlValue::Int(123)), "123");
1567 assert_eq!(
1568 format!(
1569 "{}",
1570 CqlValue::Decimal(CqlDecimal::from_signed_be_bytes_and_exponent(
1572 vec![0x01, 0xE2, 0x40],
1573 3
1574 ))
1575 ),
1576 "blobAsDecimal(0x0000000301e240)"
1577 );
1578 assert_eq!(format!("{}", CqlValue::Float(12.75)), "12.75");
1579 assert_eq!(
1580 format!("{}", CqlValue::Text("Ala ma kota".to_owned())),
1581 "'Ala ma kota'"
1582 );
1583 assert_eq!(
1584 format!("{}", CqlValue::Text("Foo's".to_owned())),
1585 "'Foo''s'"
1586 );
1587
1588 assert_eq!(
1590 format!("{}", CqlValue::Date(CqlDate(40 + (1 << 31)))),
1591 "'1970-02-10'"
1592 );
1593 assert_eq!(
1594 format!(
1595 "{}",
1596 CqlValue::Duration(CqlDuration {
1597 months: 1,
1598 days: 2,
1599 nanoseconds: 3,
1600 })
1601 ),
1602 "1mo2d3ns"
1603 );
1604 let t = chrono_04::NaiveTime::from_hms_nano_opt(6, 5, 4, 123)
1605 .unwrap()
1606 .signed_duration_since(chrono_04::NaiveTime::MIN);
1607 let t = t.num_nanoseconds().unwrap();
1608 assert_eq!(
1609 format!("{}", CqlValue::Time(CqlTime(t))),
1610 "'06:05:04.000000123'"
1611 );
1612
1613 let t = chrono_04::NaiveDate::from_ymd_opt(2005, 4, 2)
1614 .unwrap()
1615 .and_time(chrono_04::NaiveTime::from_hms_opt(19, 37, 42).unwrap());
1616 assert_eq!(
1617 format!(
1618 "{}",
1619 CqlValue::Timestamp(CqlTimestamp(
1620 t.signed_duration_since(chrono_04::NaiveDateTime::default())
1621 .num_milliseconds()
1622 ))
1623 ),
1624 "'2005-04-02 19:37:42.000+0000'"
1625 );
1626
1627 let list_or_set = vec![CqlValue::Int(1), CqlValue::Int(3), CqlValue::Int(2)];
1629 assert_eq!(
1630 format!("{}", CqlValue::List(list_or_set.clone())),
1631 "[1,3,2]"
1632 );
1633 assert_eq!(format!("{}", CqlValue::Set(list_or_set.clone())), "{1,3,2}");
1634
1635 let tuple: Vec<_> = list_or_set
1636 .into_iter()
1637 .map(Some)
1638 .chain(std::iter::once(None))
1639 .collect();
1640 assert_eq!(format!("{}", CqlValue::Tuple(tuple)), "(1,3,2,null)");
1641
1642 let map = vec![
1643 (CqlValue::Text("foo".to_owned()), CqlValue::Int(123)),
1644 (CqlValue::Text("bar".to_owned()), CqlValue::Int(321)),
1645 ];
1646 assert_eq!(format!("{}", CqlValue::Map(map)), "{'foo':123,'bar':321}");
1647
1648 let fields = vec![
1649 ("foo".to_owned(), Some(CqlValue::Int(123))),
1650 ("bar".to_owned(), Some(CqlValue::Int(321))),
1651 ];
1652 assert_eq!(
1653 format!(
1654 "{}",
1655 CqlValue::UserDefinedType {
1656 keyspace: "ks".to_owned(),
1657 name: "typ".to_owned(),
1658 fields,
1659 }
1660 ),
1661 "{foo:123,bar:321}"
1662 );
1663 }
1664}