1use std::net::IpAddr;
2use std::result::Result as StdResult;
3
4use thiserror::Error;
5use uuid::Uuid;
6
7use crate::deserialize::value::DeserializeValue;
8use crate::deserialize::value::{
9 mk_deser_err, BuiltinDeserializationErrorKind, MapIterator, UdtIterator,
10};
11use crate::deserialize::DeserializationError;
12use crate::deserialize::FrameSlice;
13use crate::frame::response::result::{CollectionType, ColumnType};
14use crate::frame::types;
15
16#[derive(Debug, Error, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17#[error("Value is too large to fit in the CQL type")]
18pub struct ValueOverflow;
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
22pub struct Unset;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
26pub struct Counter(pub i64);
27
28#[derive(Debug, Clone, Copy, Default)]
30pub enum MaybeUnset<V> {
31 #[default]
32 Unset,
33 Set(V),
34}
35
36#[derive(Debug, Clone, Copy, Eq)]
41pub struct CqlTimeuuid(Uuid);
42
43impl CqlTimeuuid {
45 pub fn as_bytes(&self) -> &[u8; 16] {
46 self.0.as_bytes()
47 }
48
49 pub fn as_u128(&self) -> u128 {
50 self.0.as_u128()
51 }
52
53 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
54 self.0.as_fields()
55 }
56
57 pub fn as_u64_pair(&self) -> (u64, u64) {
58 self.0.as_u64_pair()
59 }
60
61 pub fn from_slice(b: &[u8]) -> Result<Self, uuid::Error> {
62 Ok(Self(Uuid::from_slice(b)?))
63 }
64
65 pub fn from_slice_le(b: &[u8]) -> Result<Self, uuid::Error> {
66 Ok(Self(Uuid::from_slice_le(b)?))
67 }
68
69 pub fn from_bytes(bytes: [u8; 16]) -> Self {
70 Self(Uuid::from_bytes(bytes))
71 }
72
73 pub fn from_bytes_le(bytes: [u8; 16]) -> Self {
74 Self(Uuid::from_bytes_le(bytes))
75 }
76
77 pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
78 Self(Uuid::from_fields(d1, d2, d3, d4))
79 }
80
81 pub fn from_fields_le(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
82 Self(Uuid::from_fields_le(d1, d2, d3, d4))
83 }
84
85 pub fn from_u128(v: u128) -> Self {
86 Self(Uuid::from_u128(v))
87 }
88
89 pub fn from_u128_le(v: u128) -> Self {
90 Self(Uuid::from_u128_le(v))
91 }
92
93 pub fn from_u64_pair(high_bits: u64, low_bits: u64) -> Self {
94 Self(Uuid::from_u64_pair(high_bits, low_bits))
95 }
96}
97
98impl CqlTimeuuid {
99 fn msb(&self) -> u64 {
101 let bytes = self.0.as_bytes();
105 u64::from_be_bytes([
106 bytes[6] & 0x0f,
107 bytes[7],
108 bytes[4],
109 bytes[5],
110 bytes[0],
111 bytes[1],
112 bytes[2],
113 bytes[3],
114 ])
115 }
116
117 fn lsb(&self) -> u64 {
118 let bytes = self.0.as_bytes();
119 u64::from_be_bytes([
120 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
121 ])
122 }
123
124 fn lsb_signed(&self) -> u64 {
125 self.lsb() ^ 0x8080808080808080
126 }
127}
128
129impl std::str::FromStr for CqlTimeuuid {
130 type Err = uuid::Error;
131
132 fn from_str(s: &str) -> Result<Self, Self::Err> {
133 Ok(Self(Uuid::from_str(s)?))
134 }
135}
136
137impl std::fmt::Display for CqlTimeuuid {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(f, "{}", self.0)
140 }
141}
142
143impl AsRef<Uuid> for CqlTimeuuid {
144 fn as_ref(&self) -> &Uuid {
145 &self.0
146 }
147}
148
149impl From<CqlTimeuuid> for Uuid {
150 fn from(value: CqlTimeuuid) -> Self {
151 value.0
152 }
153}
154
155impl From<Uuid> for CqlTimeuuid {
156 fn from(value: Uuid) -> Self {
157 Self(value)
158 }
159}
160
161impl Ord for CqlTimeuuid {
169 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
170 let mut res = self.msb().cmp(&other.msb());
171 if let std::cmp::Ordering::Equal = res {
172 res = self.lsb_signed().cmp(&other.lsb_signed());
173 }
174 res
175 }
176}
177
178impl PartialOrd for CqlTimeuuid {
179 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
180 Some(self.cmp(other))
181 }
182}
183
184impl PartialEq for CqlTimeuuid {
185 fn eq(&self, other: &Self) -> bool {
186 self.cmp(other) == std::cmp::Ordering::Equal
187 }
188}
189
190impl std::hash::Hash for CqlTimeuuid {
191 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
192 self.lsb_signed().hash(state);
193 self.msb().hash(state);
194 }
195}
196
197#[derive(Clone, Eq, Debug)]
225pub struct CqlVarint(Vec<u8>);
226
227#[derive(Clone, Eq, Debug)]
232pub struct CqlVarintBorrowed<'b>(&'b [u8]);
233
234impl CqlVarint {
236 pub fn from_signed_bytes_be(digits: Vec<u8>) -> Self {
241 Self(digits)
242 }
243
244 pub fn from_signed_bytes_be_slice(digits: &[u8]) -> Self {
249 Self::from_signed_bytes_be(digits.to_vec())
250 }
251}
252
253impl<'b> CqlVarintBorrowed<'b> {
255 pub fn from_signed_bytes_be_slice(digits: &'b [u8]) -> Self {
260 Self(digits)
261 }
262}
263
264impl CqlVarint {
266 pub fn into_signed_bytes_be(self) -> Vec<u8> {
269 self.0
270 }
271
272 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
275 &self.0
276 }
277}
278
279impl CqlVarintBorrowed<'_> {
281 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
284 self.0
285 }
286}
287
288trait AsVarintSlice {
291 fn as_slice(&self) -> &[u8];
292}
293impl AsVarintSlice for CqlVarint {
294 fn as_slice(&self) -> &[u8] {
295 self.as_signed_bytes_be_slice()
296 }
297}
298impl AsVarintSlice for CqlVarintBorrowed<'_> {
299 fn as_slice(&self) -> &[u8] {
300 self.as_signed_bytes_be_slice()
301 }
302}
303
304trait AsNormalizedVarintSlice {
307 fn as_normalized_slice(&self) -> &[u8];
308}
309impl<V: AsVarintSlice> AsNormalizedVarintSlice for V {
310 fn as_normalized_slice(&self) -> &[u8] {
311 let digits = self.as_slice();
312 if digits.is_empty() {
313 return &[0];
316 }
317
318 let non_zero_position = match digits.iter().position(|b| *b != 0) {
319 Some(pos) => pos,
320 None => {
321 return &[0];
323 }
324 };
325
326 if non_zero_position > 0 {
327 let zeros_to_remove = if digits[non_zero_position] > 0x7f {
330 non_zero_position - 1
333 } else {
334 non_zero_position
336 };
337 return &digits[zeros_to_remove..];
338 }
339
340 digits
342 }
343}
344
345impl PartialEq for CqlVarint {
359 fn eq(&self, other: &Self) -> bool {
360 self.as_normalized_slice() == other.as_normalized_slice()
361 }
362}
363
364impl std::hash::Hash for CqlVarint {
366 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
367 self.as_normalized_slice().hash(state)
368 }
369}
370
371impl PartialEq for CqlVarintBorrowed<'_> {
385 fn eq(&self, other: &Self) -> bool {
386 self.as_normalized_slice() == other.as_normalized_slice()
387 }
388}
389
390impl std::hash::Hash for CqlVarintBorrowed<'_> {
392 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
393 self.as_normalized_slice().hash(state)
394 }
395}
396
397#[cfg(feature = "num-bigint-03")]
398impl From<num_bigint_03::BigInt> for CqlVarint {
399 fn from(value: num_bigint_03::BigInt) -> Self {
400 Self(value.to_signed_bytes_be())
401 }
402}
403
404#[cfg(feature = "num-bigint-03")]
405impl From<CqlVarint> for num_bigint_03::BigInt {
406 fn from(val: CqlVarint) -> Self {
407 num_bigint_03::BigInt::from_signed_bytes_be(&val.0)
408 }
409}
410
411#[cfg(feature = "num-bigint-03")]
412impl From<CqlVarintBorrowed<'_>> for num_bigint_03::BigInt {
413 fn from(val: CqlVarintBorrowed<'_>) -> Self {
414 num_bigint_03::BigInt::from_signed_bytes_be(val.0)
415 }
416}
417
418#[cfg(feature = "num-bigint-04")]
419impl From<num_bigint_04::BigInt> for CqlVarint {
420 fn from(value: num_bigint_04::BigInt) -> Self {
421 Self(value.to_signed_bytes_be())
422 }
423}
424
425#[cfg(feature = "num-bigint-04")]
426impl From<CqlVarint> for num_bigint_04::BigInt {
427 fn from(val: CqlVarint) -> Self {
428 num_bigint_04::BigInt::from_signed_bytes_be(&val.0)
429 }
430}
431
432#[cfg(feature = "num-bigint-04")]
433impl From<CqlVarintBorrowed<'_>> for num_bigint_04::BigInt {
434 fn from(val: CqlVarintBorrowed<'_>) -> Self {
435 num_bigint_04::BigInt::from_signed_bytes_be(val.0)
436 }
437}
438
439#[derive(Clone, PartialEq, Eq, Debug)]
459pub struct CqlDecimal {
460 int_val: CqlVarint,
461 scale: i32,
462}
463
464#[derive(Clone, PartialEq, Eq, Debug)]
473pub struct CqlDecimalBorrowed<'b> {
474 int_val: CqlVarintBorrowed<'b>,
475 scale: i32,
476}
477
478impl CqlDecimal {
480 pub fn from_signed_be_bytes_and_exponent(bytes: Vec<u8>, scale: i32) -> Self {
485 Self {
486 int_val: CqlVarint::from_signed_bytes_be(bytes),
487 scale,
488 }
489 }
490
491 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &[u8], scale: i32) -> Self {
496 Self::from_signed_be_bytes_and_exponent(bytes.to_vec(), scale)
497 }
498}
499
500impl<'b> CqlDecimalBorrowed<'b> {
502 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &'b [u8], scale: i32) -> Self {
507 Self {
508 int_val: CqlVarintBorrowed::from_signed_bytes_be_slice(bytes),
509 scale,
510 }
511 }
512}
513
514impl CqlDecimal {
516 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
519 (self.int_val.as_signed_bytes_be_slice(), self.scale)
520 }
521
522 pub fn into_signed_be_bytes_and_exponent(self) -> (Vec<u8>, i32) {
525 (self.int_val.into_signed_bytes_be(), self.scale)
526 }
527}
528
529impl CqlDecimalBorrowed<'_> {
531 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
534 (self.int_val.as_signed_bytes_be_slice(), self.scale)
535 }
536}
537
538#[cfg(feature = "bigdecimal-04")]
539impl From<CqlDecimal> for bigdecimal_04::BigDecimal {
540 fn from(value: CqlDecimal) -> Self {
541 Self::from((
542 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
543 value.int_val.as_signed_bytes_be_slice(),
544 ),
545 value.scale as i64,
546 ))
547 }
548}
549
550#[cfg(feature = "bigdecimal-04")]
551impl From<CqlDecimalBorrowed<'_>> for bigdecimal_04::BigDecimal {
552 fn from(value: CqlDecimalBorrowed) -> Self {
553 Self::from((
554 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
555 value.int_val.as_signed_bytes_be_slice(),
556 ),
557 value.scale as i64,
558 ))
559 }
560}
561
562#[cfg(feature = "bigdecimal-04")]
563impl TryFrom<bigdecimal_04::BigDecimal> for CqlDecimal {
564 type Error = <i64 as TryInto<i32>>::Error;
565
566 fn try_from(value: bigdecimal_04::BigDecimal) -> Result<Self, Self::Error> {
567 let (bigint, scale) = value.into_bigint_and_exponent();
568 let bytes = bigint.to_signed_bytes_be();
569 Ok(Self::from_signed_be_bytes_and_exponent(
570 bytes,
571 scale.try_into()?,
572 ))
573 }
574}
575
576#[derive(Clone, Copy, PartialEq, Eq, Debug)]
580pub struct CqlDate(pub u32);
581
582#[derive(Clone, Copy, PartialEq, Eq, Debug)]
586pub struct CqlTimestamp(pub i64);
587
588#[derive(Clone, Copy, PartialEq, Eq, Debug)]
592pub struct CqlTime(pub i64);
593
594impl CqlDate {
595 fn try_to_chrono_04_naive_date(&self) -> Result<chrono_04::NaiveDate, ValueOverflow> {
596 let days_since_unix_epoch = self.0 as i64 - (1 << 31);
597
598 let duration_since_unix_epoch =
601 chrono_04::Duration::try_days(days_since_unix_epoch).unwrap();
602
603 chrono_04::NaiveDate::from_yo_opt(1970, 1)
604 .unwrap()
605 .checked_add_signed(duration_since_unix_epoch)
606 .ok_or(ValueOverflow)
607 }
608}
609
610#[cfg(feature = "chrono-04")]
611impl From<chrono_04::NaiveDate> for CqlDate {
612 fn from(value: chrono_04::NaiveDate) -> Self {
613 let unix_epoch = chrono_04::NaiveDate::from_yo_opt(1970, 1).unwrap();
614
615 let days = ((1 << 31) + value.signed_duration_since(unix_epoch).num_days()) as u32;
618
619 Self(days)
620 }
621}
622
623#[cfg(feature = "chrono-04")]
624impl TryInto<chrono_04::NaiveDate> for CqlDate {
625 type Error = ValueOverflow;
626
627 fn try_into(self) -> Result<chrono_04::NaiveDate, Self::Error> {
628 self.try_to_chrono_04_naive_date()
629 }
630}
631
632impl CqlTimestamp {
633 fn try_to_chrono_04_datetime_utc(
634 &self,
635 ) -> Result<chrono_04::DateTime<chrono_04::Utc>, ValueOverflow> {
636 use chrono_04::TimeZone;
637 match chrono_04::Utc.timestamp_millis_opt(self.0) {
638 chrono_04::LocalResult::Single(datetime) => Ok(datetime),
639 _ => Err(ValueOverflow),
640 }
641 }
642}
643
644#[cfg(feature = "chrono-04")]
645impl From<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
646 fn from(value: chrono_04::DateTime<chrono_04::Utc>) -> Self {
647 Self(value.timestamp_millis())
648 }
649}
650
651#[cfg(feature = "chrono-04")]
652impl TryInto<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
653 type Error = ValueOverflow;
654
655 fn try_into(self) -> Result<chrono_04::DateTime<chrono_04::Utc>, Self::Error> {
656 self.try_to_chrono_04_datetime_utc()
657 }
658}
659
660#[cfg(feature = "chrono-04")]
661impl TryFrom<chrono_04::NaiveTime> for CqlTime {
662 type Error = ValueOverflow;
663
664 fn try_from(value: chrono_04::NaiveTime) -> Result<Self, Self::Error> {
665 let nanos = value
666 .signed_duration_since(chrono_04::NaiveTime::MIN)
667 .num_nanoseconds()
668 .unwrap();
669
670 if nanos <= 86399999999999 {
672 Ok(Self(nanos))
673 } else {
674 Err(ValueOverflow)
675 }
676 }
677}
678
679#[cfg(feature = "chrono-04")]
680impl TryInto<chrono_04::NaiveTime> for CqlTime {
681 type Error = ValueOverflow;
682
683 fn try_into(self) -> Result<chrono_04::NaiveTime, Self::Error> {
684 let secs = (self.0 / 1_000_000_000)
685 .try_into()
686 .map_err(|_| ValueOverflow)?;
687 let nanos = (self.0 % 1_000_000_000)
688 .try_into()
689 .map_err(|_| ValueOverflow)?;
690 chrono_04::NaiveTime::from_num_seconds_from_midnight_opt(secs, nanos).ok_or(ValueOverflow)
691 }
692}
693
694#[cfg(feature = "time-03")]
695impl From<time_03::Date> for CqlDate {
696 fn from(value: time_03::Date) -> Self {
697 const JULIAN_DAY_OFFSET: i64 =
698 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
699
700 const _: () = assert!(
702 time_03::Date::MAX.to_julian_day() as i64 + JULIAN_DAY_OFFSET < u32::MAX as i64
703 );
704 const _: () = assert!(
705 time_03::Date::MIN.to_julian_day() as i64 + JULIAN_DAY_OFFSET > u32::MIN as i64
706 );
707
708 let days = value.to_julian_day() as i64 + JULIAN_DAY_OFFSET;
709
710 Self(days as u32)
711 }
712}
713
714#[cfg(feature = "time-03")]
715impl TryInto<time_03::Date> for CqlDate {
716 type Error = ValueOverflow;
717
718 fn try_into(self) -> Result<time_03::Date, Self::Error> {
719 const JULIAN_DAY_OFFSET: i64 =
720 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
721
722 let julian_days = (self.0 as i64 - JULIAN_DAY_OFFSET)
723 .try_into()
724 .map_err(|_| ValueOverflow)?;
725
726 time_03::Date::from_julian_day(julian_days).map_err(|_| ValueOverflow)
727 }
728}
729
730#[cfg(feature = "time-03")]
731impl From<time_03::OffsetDateTime> for CqlTimestamp {
732 fn from(value: time_03::OffsetDateTime) -> Self {
733 const _: () = assert!(
736 time_03::PrimitiveDateTime::MAX
737 .assume_utc()
738 .unix_timestamp_nanos()
739 / 1_000_000
741 < i64::MAX as i128
742 );
743 const _: () = assert!(
744 time_03::PrimitiveDateTime::MIN
745 .assume_utc()
746 .unix_timestamp_nanos()
747 / 1_000_000
748 > i64::MIN as i128
749 );
750
751 Self(value.unix_timestamp() * 1000 + value.millisecond() as i64)
753 }
754}
755
756#[cfg(feature = "time-03")]
757impl TryInto<time_03::OffsetDateTime> for CqlTimestamp {
758 type Error = ValueOverflow;
759
760 fn try_into(self) -> Result<time_03::OffsetDateTime, Self::Error> {
761 time_03::OffsetDateTime::from_unix_timestamp_nanos(self.0 as i128 * 1_000_000)
762 .map_err(|_| ValueOverflow)
763 }
764}
765
766#[cfg(feature = "time-03")]
767impl From<time_03::Time> for CqlTime {
768 fn from(value: time_03::Time) -> Self {
769 let (h, m, s, n) = value.as_hms_nano();
770
771 let nanos = (h as i64 * 3600 + m as i64 * 60 + s as i64) * 1_000_000_000 + n as i64;
773
774 Self(nanos)
775 }
776}
777
778#[cfg(feature = "time-03")]
779impl TryInto<time_03::Time> for CqlTime {
780 type Error = ValueOverflow;
781
782 fn try_into(self) -> Result<time_03::Time, Self::Error> {
783 let h = self.0 / 3_600_000_000_000;
784 let m = self.0 / 60_000_000_000 % 60;
785 let s = self.0 / 1_000_000_000 % 60;
786 let n = self.0 % 1_000_000_000;
787
788 time_03::Time::from_hms_nano(
789 h.try_into().map_err(|_| ValueOverflow)?,
790 m as u8,
791 s as u8,
792 n as u32,
793 )
794 .map_err(|_| ValueOverflow)
795 }
796}
797
798#[derive(Clone, Debug, Copy, PartialEq, Eq)]
800pub struct CqlDuration {
801 pub months: i32,
802 pub days: i32,
803 pub nanoseconds: i64,
804}
805
806#[derive(Clone, Debug, PartialEq)]
807#[non_exhaustive]
808pub enum CqlValue {
809 Ascii(String),
810 Boolean(bool),
811 Blob(Vec<u8>),
812 Counter(Counter),
813 Decimal(CqlDecimal),
814 Date(CqlDate),
817 Double(f64),
818 Duration(CqlDuration),
819 Empty,
820 Float(f32),
821 Int(i32),
822 BigInt(i64),
823 Text(String),
824 Timestamp(CqlTimestamp),
826 Inet(IpAddr),
827 List(Vec<CqlValue>),
828 Map(Vec<(CqlValue, CqlValue)>),
829 Set(Vec<CqlValue>),
830 UserDefinedType {
831 keyspace: String,
832 name: String,
833 fields: Vec<(String, Option<CqlValue>)>,
837 },
838 SmallInt(i16),
839 TinyInt(i8),
840 Time(CqlTime),
842 Timeuuid(CqlTimeuuid),
843 Tuple(Vec<Option<CqlValue>>),
844 Uuid(Uuid),
845 Varint(CqlVarint),
846}
847
848impl CqlValue {
849 pub fn as_ascii(&self) -> Option<&String> {
850 match self {
851 Self::Ascii(s) => Some(s),
852 _ => None,
853 }
854 }
855
856 pub fn as_cql_date(&self) -> Option<CqlDate> {
857 match self {
858 Self::Date(d) => Some(*d),
859 _ => None,
860 }
861 }
862
863 #[cfg(test)]
864 #[cfg(feature = "chrono-04")]
865 pub(crate) fn as_naive_date_04(&self) -> Option<chrono_04::NaiveDate> {
866 self.as_cql_date().and_then(|date| date.try_into().ok())
867 }
868
869 #[cfg(test)]
870 #[cfg(feature = "time-03")]
871 pub(crate) fn as_date_03(&self) -> Option<time_03::Date> {
872 self.as_cql_date().and_then(|date| date.try_into().ok())
873 }
874
875 pub fn as_cql_timestamp(&self) -> Option<CqlTimestamp> {
876 match self {
877 Self::Timestamp(i) => Some(*i),
878 _ => None,
879 }
880 }
881
882 #[cfg(test)]
883 #[cfg(feature = "chrono-04")]
884 pub(crate) fn as_datetime_04(&self) -> Option<chrono_04::DateTime<chrono_04::Utc>> {
885 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
886 }
887
888 #[cfg(test)]
889 #[cfg(feature = "time-03")]
890 pub(crate) fn as_offset_date_time_03(&self) -> Option<time_03::OffsetDateTime> {
891 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
892 }
893
894 pub fn as_cql_time(&self) -> Option<CqlTime> {
895 match self {
896 Self::Time(i) => Some(*i),
897 _ => None,
898 }
899 }
900
901 #[cfg(test)]
902 #[cfg(feature = "chrono-04")]
903 pub(crate) fn as_naive_time_04(&self) -> Option<chrono_04::NaiveTime> {
904 self.as_cql_time().and_then(|ts| ts.try_into().ok())
905 }
906
907 #[cfg(test)]
908 #[cfg(feature = "time-03")]
909 pub(crate) fn as_time_03(&self) -> Option<time_03::Time> {
910 self.as_cql_time().and_then(|ts| ts.try_into().ok())
911 }
912
913 pub fn as_cql_duration(&self) -> Option<CqlDuration> {
914 match self {
915 Self::Duration(i) => Some(*i),
916 _ => None,
917 }
918 }
919
920 pub fn as_counter(&self) -> Option<Counter> {
921 match self {
922 Self::Counter(i) => Some(*i),
923 _ => None,
924 }
925 }
926
927 pub fn as_boolean(&self) -> Option<bool> {
928 match self {
929 Self::Boolean(i) => Some(*i),
930 _ => None,
931 }
932 }
933
934 pub fn as_double(&self) -> Option<f64> {
935 match self {
936 Self::Double(d) => Some(*d),
937 _ => None,
938 }
939 }
940
941 pub fn as_uuid(&self) -> Option<Uuid> {
942 match self {
943 Self::Uuid(u) => Some(*u),
944 _ => None,
945 }
946 }
947
948 pub fn as_float(&self) -> Option<f32> {
949 match self {
950 Self::Float(f) => Some(*f),
951 _ => None,
952 }
953 }
954
955 pub fn as_int(&self) -> Option<i32> {
956 match self {
957 Self::Int(i) => Some(*i),
958 _ => None,
959 }
960 }
961
962 pub fn as_bigint(&self) -> Option<i64> {
963 match self {
964 Self::BigInt(i) => Some(*i),
965 _ => None,
966 }
967 }
968
969 pub fn as_tinyint(&self) -> Option<i8> {
970 match self {
971 Self::TinyInt(i) => Some(*i),
972 _ => None,
973 }
974 }
975
976 pub fn as_smallint(&self) -> Option<i16> {
977 match self {
978 Self::SmallInt(i) => Some(*i),
979 _ => None,
980 }
981 }
982
983 pub fn as_blob(&self) -> Option<&Vec<u8>> {
984 match self {
985 Self::Blob(v) => Some(v),
986 _ => None,
987 }
988 }
989
990 pub fn as_text(&self) -> Option<&String> {
991 match self {
992 Self::Text(s) => Some(s),
993 _ => None,
994 }
995 }
996
997 pub fn as_timeuuid(&self) -> Option<CqlTimeuuid> {
998 match self {
999 Self::Timeuuid(u) => Some(*u),
1000 _ => None,
1001 }
1002 }
1003
1004 pub fn into_string(self) -> Option<String> {
1005 match self {
1006 Self::Ascii(s) => Some(s),
1007 Self::Text(s) => Some(s),
1008 _ => None,
1009 }
1010 }
1011
1012 pub fn into_blob(self) -> Option<Vec<u8>> {
1013 match self {
1014 Self::Blob(b) => Some(b),
1015 _ => None,
1016 }
1017 }
1018
1019 pub fn as_inet(&self) -> Option<IpAddr> {
1020 match self {
1021 Self::Inet(a) => Some(*a),
1022 _ => None,
1023 }
1024 }
1025
1026 pub fn as_list(&self) -> Option<&Vec<CqlValue>> {
1027 match self {
1028 Self::List(s) => Some(s),
1029 _ => None,
1030 }
1031 }
1032
1033 pub fn as_set(&self) -> Option<&Vec<CqlValue>> {
1034 match self {
1035 Self::Set(s) => Some(s),
1036 _ => None,
1037 }
1038 }
1039
1040 pub fn as_map(&self) -> Option<&Vec<(CqlValue, CqlValue)>> {
1041 match self {
1042 Self::Map(s) => Some(s),
1043 _ => None,
1044 }
1045 }
1046
1047 pub fn as_udt(&self) -> Option<&Vec<(String, Option<CqlValue>)>> {
1048 match self {
1049 Self::UserDefinedType { fields, .. } => Some(fields),
1050 _ => None,
1051 }
1052 }
1053
1054 pub fn into_vec(self) -> Option<Vec<CqlValue>> {
1055 match self {
1056 Self::List(s) => Some(s),
1057 Self::Set(s) => Some(s),
1058 _ => None,
1059 }
1060 }
1061
1062 pub fn into_pair_vec(self) -> Option<Vec<(CqlValue, CqlValue)>> {
1063 match self {
1064 Self::Map(s) => Some(s),
1065 _ => None,
1066 }
1067 }
1068
1069 pub fn into_udt_pair_vec(self) -> Option<Vec<(String, Option<CqlValue>)>> {
1070 match self {
1071 Self::UserDefinedType { fields, .. } => Some(fields),
1072 _ => None,
1073 }
1074 }
1075
1076 pub fn into_cql_varint(self) -> Option<CqlVarint> {
1077 match self {
1078 Self::Varint(i) => Some(i),
1079 _ => None,
1080 }
1081 }
1082
1083 pub fn into_cql_decimal(self) -> Option<CqlDecimal> {
1084 match self {
1085 Self::Decimal(i) => Some(i),
1086 _ => None,
1087 }
1088 }
1089 }
1091
1092impl std::fmt::Display for CqlValue {
1095 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1096 use crate::pretty::{
1097 CqlStringLiteralDisplayer, HexBytes, MaybeNullDisplayer, PairDisplayer,
1098 };
1099 use itertools::Itertools;
1100
1101 match self {
1102 CqlValue::Ascii(a) => write!(f, "{}", CqlStringLiteralDisplayer(a))?,
1104 CqlValue::Text(t) => write!(f, "{}", CqlStringLiteralDisplayer(t))?,
1105 CqlValue::Blob(b) => write!(f, "0x{:x}", HexBytes(b))?,
1106 CqlValue::Empty => write!(f, "0x")?,
1107 CqlValue::Decimal(d) => {
1108 let (bytes, scale) = d.as_signed_be_bytes_slice_and_exponent();
1109 write!(
1110 f,
1111 "blobAsDecimal(0x{:x}{:x})",
1112 HexBytes(&scale.to_be_bytes()),
1113 HexBytes(bytes)
1114 )?
1115 }
1116 CqlValue::Float(fl) => write!(f, "{}", fl)?,
1117 CqlValue::Double(d) => write!(f, "{}", d)?,
1118 CqlValue::Boolean(b) => write!(f, "{}", b)?,
1119 CqlValue::Int(i) => write!(f, "{}", i)?,
1120 CqlValue::BigInt(bi) => write!(f, "{}", bi)?,
1121 CqlValue::Inet(i) => write!(f, "'{}'", i)?,
1122 CqlValue::SmallInt(si) => write!(f, "{}", si)?,
1123 CqlValue::TinyInt(ti) => write!(f, "{}", ti)?,
1124 CqlValue::Varint(vi) => write!(
1125 f,
1126 "blobAsVarint(0x{:x})",
1127 HexBytes(vi.as_signed_bytes_be_slice())
1128 )?,
1129 CqlValue::Counter(c) => write!(f, "{}", c.0)?,
1130 CqlValue::Date(d) => {
1131 match d.try_to_chrono_04_naive_date() {
1134 Ok(d) => write!(f, "'{}'", d)?,
1135 Err(_) => f.write_str("<date out of representable range>")?,
1136 }
1137 }
1138 CqlValue::Duration(d) => write!(f, "{}mo{}d{}ns", d.months, d.days, d.nanoseconds)?,
1139 CqlValue::Time(CqlTime(t)) => {
1140 write!(
1141 f,
1142 "'{:02}:{:02}:{:02}.{:09}'",
1143 t / 3_600_000_000_000,
1144 t / 60_000_000_000 % 60,
1145 t / 1_000_000_000 % 60,
1146 t % 1_000_000_000,
1147 )?;
1148 }
1149 CqlValue::Timestamp(ts) => match ts.try_to_chrono_04_datetime_utc() {
1150 Ok(d) => write!(f, "{}", d.format("'%Y-%m-%d %H:%M:%S%.3f%z'"))?,
1151 Err(_) => f.write_str("<timestamp out of representable range>")?,
1152 },
1153 CqlValue::Timeuuid(t) => write!(f, "{}", t)?,
1154 CqlValue::Uuid(u) => write!(f, "{}", u)?,
1155
1156 CqlValue::Tuple(t) => {
1158 f.write_str("(")?;
1159 t.iter()
1160 .map(|x| MaybeNullDisplayer(x.as_ref()))
1161 .format(",")
1162 .fmt(f)?;
1163 f.write_str(")")?;
1164 }
1165 CqlValue::List(v) => {
1166 f.write_str("[")?;
1167 v.iter().format(",").fmt(f)?;
1168 f.write_str("]")?;
1169 }
1170 CqlValue::Set(v) => {
1171 f.write_str("{")?;
1172 v.iter().format(",").fmt(f)?;
1173 f.write_str("}")?;
1174 }
1175 CqlValue::Map(m) => {
1176 f.write_str("{")?;
1177 m.iter()
1178 .map(|(k, v)| PairDisplayer(k, v))
1179 .format(",")
1180 .fmt(f)?;
1181 f.write_str("}")?;
1182 }
1183 CqlValue::UserDefinedType {
1184 keyspace: _,
1185 name: _,
1186 fields,
1187 } => {
1188 f.write_str("{")?;
1189 fields
1190 .iter()
1191 .map(|(k, v)| PairDisplayer(k, MaybeNullDisplayer(v.as_ref())))
1192 .format(",")
1193 .fmt(f)?;
1194 f.write_str("}")?;
1195 }
1196 }
1197 Ok(())
1198 }
1199}
1200
1201pub fn deser_cql_value(
1202 typ: &ColumnType,
1203 buf: &mut &[u8],
1204) -> StdResult<CqlValue, DeserializationError> {
1205 use crate::frame::response::result::ColumnType::*;
1206 use crate::frame::response::result::NativeType::*;
1207
1208 if buf.is_empty() {
1209 match typ {
1210 Native(Ascii) | Native(Blob) | Native(Text) => {
1211 }
1213 _ => return Ok(CqlValue::Empty),
1214 }
1215 }
1216 let v = Some(FrameSlice::new_borrowed(buf));
1221
1222 Ok(match typ {
1223 Native(Ascii) => {
1224 let s = String::deserialize(typ, v)?;
1225 CqlValue::Ascii(s)
1226 }
1227 Native(Boolean) => {
1228 let b = bool::deserialize(typ, v)?;
1229 CqlValue::Boolean(b)
1230 }
1231 Native(Blob) => {
1232 let b = Vec::<u8>::deserialize(typ, v)?;
1233 CqlValue::Blob(b)
1234 }
1235 Native(Date) => {
1236 let d = CqlDate::deserialize(typ, v)?;
1237 CqlValue::Date(d)
1238 }
1239 Native(Counter) => {
1240 let c = crate::value::Counter::deserialize(typ, v)?;
1241 CqlValue::Counter(c)
1242 }
1243 Native(Decimal) => {
1244 let d = CqlDecimal::deserialize(typ, v)?;
1245 CqlValue::Decimal(d)
1246 }
1247 Native(Double) => {
1248 let d = f64::deserialize(typ, v)?;
1249 CqlValue::Double(d)
1250 }
1251 Native(Float) => {
1252 let f = f32::deserialize(typ, v)?;
1253 CqlValue::Float(f)
1254 }
1255 Native(Int) => {
1256 let i = i32::deserialize(typ, v)?;
1257 CqlValue::Int(i)
1258 }
1259 Native(SmallInt) => {
1260 let si = i16::deserialize(typ, v)?;
1261 CqlValue::SmallInt(si)
1262 }
1263 Native(TinyInt) => {
1264 let ti = i8::deserialize(typ, v)?;
1265 CqlValue::TinyInt(ti)
1266 }
1267 Native(BigInt) => {
1268 let bi = i64::deserialize(typ, v)?;
1269 CqlValue::BigInt(bi)
1270 }
1271 Native(Text) => {
1272 let s = String::deserialize(typ, v)?;
1273 CqlValue::Text(s)
1274 }
1275 Native(Timestamp) => {
1276 let t = CqlTimestamp::deserialize(typ, v)?;
1277 CqlValue::Timestamp(t)
1278 }
1279 Native(Time) => {
1280 let t = CqlTime::deserialize(typ, v)?;
1281 CqlValue::Time(t)
1282 }
1283 Native(Timeuuid) => {
1284 let t = CqlTimeuuid::deserialize(typ, v)?;
1285 CqlValue::Timeuuid(t)
1286 }
1287 Native(Duration) => {
1288 let d = CqlDuration::deserialize(typ, v)?;
1289 CqlValue::Duration(d)
1290 }
1291 Native(Inet) => {
1292 let i = IpAddr::deserialize(typ, v)?;
1293 CqlValue::Inet(i)
1294 }
1295 Native(Uuid) => {
1296 let uuid = uuid::Uuid::deserialize(typ, v)?;
1297 CqlValue::Uuid(uuid)
1298 }
1299 Native(Varint) => {
1300 let vi = CqlVarint::deserialize(typ, v)?;
1301 CqlValue::Varint(vi)
1302 }
1303 Collection {
1304 typ: CollectionType::List(_type_name),
1305 ..
1306 } => {
1307 let l = Vec::<CqlValue>::deserialize(typ, v)?;
1308 CqlValue::List(l)
1309 }
1310 Collection {
1311 typ: CollectionType::Map(_key_type, _value_type),
1312 ..
1313 } => {
1314 let iter = MapIterator::<'_, '_, CqlValue, CqlValue>::deserialize(typ, v)?;
1315 let m: Vec<(CqlValue, CqlValue)> = iter.collect::<StdResult<_, _>>()?;
1316 CqlValue::Map(m)
1317 }
1318 Collection {
1319 typ: CollectionType::Set(_type_name),
1320 ..
1321 } => {
1322 let s = Vec::<CqlValue>::deserialize(typ, v)?;
1323 CqlValue::Set(s)
1324 }
1325 Vector { .. } => {
1326 return Err(mk_deser_err::<CqlValue>(
1327 typ,
1328 BuiltinDeserializationErrorKind::Unsupported,
1329 ))
1330 }
1331 UserDefinedType {
1332 definition: udt, ..
1333 } => {
1334 let iter = UdtIterator::deserialize(typ, v)?;
1335 let fields: Vec<(String, Option<CqlValue>)> = iter
1336 .map(|((col_name, col_type), res)| {
1337 res.and_then(|v| {
1338 let val = Option::<CqlValue>::deserialize(col_type, v.flatten())?;
1339 Ok((col_name.clone().into_owned(), val))
1340 })
1341 })
1342 .collect::<StdResult<_, _>>()?;
1343
1344 CqlValue::UserDefinedType {
1345 keyspace: udt.keyspace.clone().into_owned(),
1346 name: udt.name.clone().into_owned(),
1347 fields,
1348 }
1349 }
1350 Tuple(type_names) => {
1351 let t = type_names
1352 .iter()
1353 .map(|typ| -> StdResult<_, DeserializationError> {
1354 let raw = types::read_bytes_opt(buf).map_err(|e| {
1355 mk_deser_err::<CqlValue>(
1356 typ,
1357 BuiltinDeserializationErrorKind::RawCqlBytesReadError(e),
1358 )
1359 })?;
1360 raw.map(|v| CqlValue::deserialize(typ, Some(FrameSlice::new_borrowed(v))))
1361 .transpose()
1362 })
1363 .collect::<StdResult<_, _>>()?;
1364 CqlValue::Tuple(t)
1365 }
1366 })
1367}
1368
1369#[derive(Debug, Default, PartialEq)]
1370pub struct Row {
1371 pub columns: Vec<Option<CqlValue>>,
1372}
1373
1374#[cfg(test)]
1375mod tests {
1376 use std::str::FromStr as _;
1377
1378 use super::*;
1379
1380 #[test]
1381 fn timeuuid_msb_byte_order() {
1382 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1383
1384 assert_eq!(0x0607040500010203, uuid.msb());
1385 }
1386
1387 #[test]
1388 fn timeuuid_msb_clears_version_bits() {
1389 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1391
1392 assert_eq!(0x0fffffffffffffff, uuid.msb());
1393 }
1394
1395 #[test]
1396 fn timeuuid_lsb_byte_order() {
1397 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1398
1399 assert_eq!(0x08090a0b0c0d0e0f, uuid.lsb());
1400 }
1401
1402 #[test]
1403 fn timeuuid_lsb_modifies_no_bits() {
1404 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1405
1406 assert_eq!(0xffffffffffffffff, uuid.lsb());
1407 }
1408
1409 #[test]
1410 fn test_cql_value_displayer() {
1411 assert_eq!(format!("{}", CqlValue::Boolean(true)), "true");
1412 assert_eq!(format!("{}", CqlValue::Int(123)), "123");
1413 assert_eq!(
1414 format!(
1415 "{}",
1416 CqlValue::Decimal(CqlDecimal::from_signed_be_bytes_and_exponent(
1418 vec![0x01, 0xE2, 0x40],
1419 3
1420 ))
1421 ),
1422 "blobAsDecimal(0x0000000301e240)"
1423 );
1424 assert_eq!(format!("{}", CqlValue::Float(12.75)), "12.75");
1425 assert_eq!(
1426 format!("{}", CqlValue::Text("Ala ma kota".to_owned())),
1427 "'Ala ma kota'"
1428 );
1429 assert_eq!(
1430 format!("{}", CqlValue::Text("Foo's".to_owned())),
1431 "'Foo''s'"
1432 );
1433
1434 assert_eq!(
1436 format!("{}", CqlValue::Date(CqlDate(40 + (1 << 31)))),
1437 "'1970-02-10'"
1438 );
1439 assert_eq!(
1440 format!(
1441 "{}",
1442 CqlValue::Duration(CqlDuration {
1443 months: 1,
1444 days: 2,
1445 nanoseconds: 3,
1446 })
1447 ),
1448 "1mo2d3ns"
1449 );
1450 let t = chrono_04::NaiveTime::from_hms_nano_opt(6, 5, 4, 123)
1451 .unwrap()
1452 .signed_duration_since(chrono_04::NaiveTime::MIN);
1453 let t = t.num_nanoseconds().unwrap();
1454 assert_eq!(
1455 format!("{}", CqlValue::Time(CqlTime(t))),
1456 "'06:05:04.000000123'"
1457 );
1458
1459 let t = chrono_04::NaiveDate::from_ymd_opt(2005, 4, 2)
1460 .unwrap()
1461 .and_time(chrono_04::NaiveTime::from_hms_opt(19, 37, 42).unwrap());
1462 assert_eq!(
1463 format!(
1464 "{}",
1465 CqlValue::Timestamp(CqlTimestamp(
1466 t.signed_duration_since(chrono_04::NaiveDateTime::default())
1467 .num_milliseconds()
1468 ))
1469 ),
1470 "'2005-04-02 19:37:42.000+0000'"
1471 );
1472
1473 let list_or_set = vec![CqlValue::Int(1), CqlValue::Int(3), CqlValue::Int(2)];
1475 assert_eq!(
1476 format!("{}", CqlValue::List(list_or_set.clone())),
1477 "[1,3,2]"
1478 );
1479 assert_eq!(format!("{}", CqlValue::Set(list_or_set.clone())), "{1,3,2}");
1480
1481 let tuple: Vec<_> = list_or_set
1482 .into_iter()
1483 .map(Some)
1484 .chain(std::iter::once(None))
1485 .collect();
1486 assert_eq!(format!("{}", CqlValue::Tuple(tuple)), "(1,3,2,null)");
1487
1488 let map = vec![
1489 (CqlValue::Text("foo".to_owned()), CqlValue::Int(123)),
1490 (CqlValue::Text("bar".to_owned()), CqlValue::Int(321)),
1491 ];
1492 assert_eq!(format!("{}", CqlValue::Map(map)), "{'foo':123,'bar':321}");
1493
1494 let fields = vec![
1495 ("foo".to_owned(), Some(CqlValue::Int(123))),
1496 ("bar".to_owned(), Some(CqlValue::Int(321))),
1497 ];
1498 assert_eq!(
1499 format!(
1500 "{}",
1501 CqlValue::UserDefinedType {
1502 keyspace: "ks".to_owned(),
1503 name: "typ".to_owned(),
1504 fields,
1505 }
1506 ),
1507 "{foo:123,bar:321}"
1508 );
1509 }
1510}