1use std::net::IpAddr;
5use std::result::Result as StdResult;
6
7use thiserror::Error;
8use uuid::Uuid;
9
10use crate::deserialize::DeserializationError;
11use crate::deserialize::FrameSlice;
12use crate::deserialize::value::DeserializeValue;
13use crate::deserialize::value::{
14 BuiltinDeserializationErrorKind, MapIterator, UdtIterator, VectorIterator, mk_deser_err,
15};
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
60pub trait Emptiable {}
71
72#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
81pub enum MaybeEmpty<T: Emptiable> {
82 Empty,
84 Value(T),
86}
87
88#[derive(Debug, Clone, Copy, Eq)]
93pub struct CqlTimeuuid(Uuid);
94
95impl CqlTimeuuid {
97 pub fn nil() -> Self {
100 Self(Uuid::nil())
101 }
102
103 pub fn as_bytes(&self) -> &[u8; 16] {
106 self.0.as_bytes()
107 }
108
109 pub fn as_u128(&self) -> u128 {
112 self.0.as_u128()
113 }
114
115 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
118 self.0.as_fields()
119 }
120
121 pub fn as_u64_pair(&self) -> (u64, u64) {
124 self.0.as_u64_pair()
125 }
126
127 pub fn from_slice(b: &[u8]) -> Result<Self, uuid::Error> {
130 Ok(Self(Uuid::from_slice(b)?))
131 }
132
133 pub fn from_slice_le(b: &[u8]) -> Result<Self, uuid::Error> {
136 Ok(Self(Uuid::from_slice_le(b)?))
137 }
138
139 pub fn from_bytes(bytes: [u8; 16]) -> Self {
142 Self(Uuid::from_bytes(bytes))
143 }
144
145 pub fn from_bytes_le(bytes: [u8; 16]) -> Self {
148 Self(Uuid::from_bytes_le(bytes))
149 }
150
151 pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
154 Self(Uuid::from_fields(d1, d2, d3, d4))
155 }
156
157 pub fn from_fields_le(d1: u32, d2: u16, d3: u16, d4: &[u8; 8]) -> Self {
160 Self(Uuid::from_fields_le(d1, d2, d3, d4))
161 }
162
163 pub fn from_u128(v: u128) -> Self {
166 Self(Uuid::from_u128(v))
167 }
168
169 pub fn from_u128_le(v: u128) -> Self {
172 Self(Uuid::from_u128_le(v))
173 }
174
175 pub fn from_u64_pair(high_bits: u64, low_bits: u64) -> Self {
178 Self(Uuid::from_u64_pair(high_bits, low_bits))
179 }
180}
181
182impl CqlTimeuuid {
183 fn msb(&self) -> u64 {
185 let bytes = self.0.as_bytes();
189 u64::from_be_bytes([
190 bytes[6] & 0x0f,
191 bytes[7],
192 bytes[4],
193 bytes[5],
194 bytes[0],
195 bytes[1],
196 bytes[2],
197 bytes[3],
198 ])
199 }
200
201 fn lsb(&self) -> u64 {
202 let bytes = self.0.as_bytes();
203 u64::from_be_bytes([
204 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
205 ])
206 }
207
208 fn lsb_signed(&self) -> u64 {
209 self.lsb() ^ 0x8080808080808080
210 }
211}
212
213impl std::str::FromStr for CqlTimeuuid {
214 type Err = uuid::Error;
215
216 fn from_str(s: &str) -> Result<Self, Self::Err> {
217 Ok(Self(Uuid::from_str(s)?))
218 }
219}
220
221impl std::fmt::Display for CqlTimeuuid {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 write!(f, "{}", self.0)
224 }
225}
226
227impl AsRef<Uuid> for CqlTimeuuid {
228 fn as_ref(&self) -> &Uuid {
229 &self.0
230 }
231}
232
233impl From<CqlTimeuuid> for Uuid {
234 fn from(value: CqlTimeuuid) -> Self {
235 value.0
236 }
237}
238
239impl From<Uuid> for CqlTimeuuid {
240 fn from(value: Uuid) -> Self {
241 Self(value)
242 }
243}
244
245impl Ord for CqlTimeuuid {
253 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
254 let mut res = self.msb().cmp(&other.msb());
255 if let std::cmp::Ordering::Equal = res {
256 res = self.lsb_signed().cmp(&other.lsb_signed());
257 }
258 res
259 }
260}
261
262impl PartialOrd for CqlTimeuuid {
263 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
264 Some(self.cmp(other))
265 }
266}
267
268impl PartialEq for CqlTimeuuid {
269 fn eq(&self, other: &Self) -> bool {
270 self.cmp(other) == std::cmp::Ordering::Equal
271 }
272}
273
274impl std::hash::Hash for CqlTimeuuid {
275 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
276 self.lsb_signed().hash(state);
277 self.msb().hash(state);
278 }
279}
280
281#[derive(Clone, Eq, Debug)]
309pub struct CqlVarint(Vec<u8>);
310
311#[derive(Clone, Eq, Debug)]
316pub struct CqlVarintBorrowed<'b>(&'b [u8]);
317
318impl CqlVarint {
320 pub fn from_signed_bytes_be(digits: Vec<u8>) -> Self {
325 Self(digits)
326 }
327
328 pub fn from_signed_bytes_be_slice(digits: &[u8]) -> Self {
333 Self::from_signed_bytes_be(digits.to_vec())
334 }
335}
336
337impl<'b> CqlVarintBorrowed<'b> {
339 pub fn from_signed_bytes_be_slice(digits: &'b [u8]) -> Self {
344 Self(digits)
345 }
346}
347
348impl CqlVarint {
350 pub fn into_signed_bytes_be(self) -> Vec<u8> {
353 self.0
354 }
355
356 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
359 &self.0
360 }
361}
362
363impl CqlVarintBorrowed<'_> {
365 pub fn as_signed_bytes_be_slice(&self) -> &[u8] {
368 self.0
369 }
370}
371
372trait AsVarintSlice {
375 fn as_slice(&self) -> &[u8];
376}
377impl AsVarintSlice for CqlVarint {
378 fn as_slice(&self) -> &[u8] {
379 self.as_signed_bytes_be_slice()
380 }
381}
382impl AsVarintSlice for CqlVarintBorrowed<'_> {
383 fn as_slice(&self) -> &[u8] {
384 self.as_signed_bytes_be_slice()
385 }
386}
387
388trait AsNormalizedVarintSlice {
391 fn as_normalized_slice(&self) -> &[u8];
392}
393impl<V: AsVarintSlice> AsNormalizedVarintSlice for V {
394 fn as_normalized_slice(&self) -> &[u8] {
395 let digits = self.as_slice();
396 if digits.is_empty() {
397 return &[0];
400 }
401
402 let non_zero_position = match digits.iter().position(|b| *b != 0) {
403 Some(pos) => pos,
404 None => {
405 return &[0];
407 }
408 };
409
410 if non_zero_position > 0 {
411 let zeros_to_remove = if digits[non_zero_position] > 0x7f {
414 non_zero_position - 1
417 } else {
418 non_zero_position
420 };
421 return &digits[zeros_to_remove..];
422 }
423
424 digits
426 }
427}
428
429impl PartialEq for CqlVarint {
443 fn eq(&self, other: &Self) -> bool {
444 self.as_normalized_slice() == other.as_normalized_slice()
445 }
446}
447
448impl std::hash::Hash for CqlVarint {
450 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
451 self.as_normalized_slice().hash(state)
452 }
453}
454
455impl PartialEq for CqlVarintBorrowed<'_> {
469 fn eq(&self, other: &Self) -> bool {
470 self.as_normalized_slice() == other.as_normalized_slice()
471 }
472}
473
474impl std::hash::Hash for CqlVarintBorrowed<'_> {
476 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
477 self.as_normalized_slice().hash(state)
478 }
479}
480
481#[cfg(feature = "num-bigint-03")]
482impl From<num_bigint_03::BigInt> for CqlVarint {
483 fn from(value: num_bigint_03::BigInt) -> Self {
484 Self(value.to_signed_bytes_be())
485 }
486}
487
488#[cfg(feature = "num-bigint-03")]
489impl From<CqlVarint> for num_bigint_03::BigInt {
490 fn from(val: CqlVarint) -> Self {
491 num_bigint_03::BigInt::from_signed_bytes_be(&val.0)
492 }
493}
494
495#[cfg(feature = "num-bigint-03")]
496impl From<CqlVarintBorrowed<'_>> for num_bigint_03::BigInt {
497 fn from(val: CqlVarintBorrowed<'_>) -> Self {
498 num_bigint_03::BigInt::from_signed_bytes_be(val.0)
499 }
500}
501
502#[cfg(feature = "num-bigint-04")]
503impl From<num_bigint_04::BigInt> for CqlVarint {
504 fn from(value: num_bigint_04::BigInt) -> Self {
505 Self(value.to_signed_bytes_be())
506 }
507}
508
509#[cfg(feature = "num-bigint-04")]
510impl From<CqlVarint> for num_bigint_04::BigInt {
511 fn from(val: CqlVarint) -> Self {
512 num_bigint_04::BigInt::from_signed_bytes_be(&val.0)
513 }
514}
515
516#[cfg(feature = "num-bigint-04")]
517impl From<CqlVarintBorrowed<'_>> for num_bigint_04::BigInt {
518 fn from(val: CqlVarintBorrowed<'_>) -> Self {
519 num_bigint_04::BigInt::from_signed_bytes_be(val.0)
520 }
521}
522
523#[derive(Clone, PartialEq, Eq, Debug)]
543pub struct CqlDecimal {
544 int_val: CqlVarint,
545 scale: i32,
546}
547
548#[derive(Clone, PartialEq, Eq, Debug)]
557pub struct CqlDecimalBorrowed<'b> {
558 int_val: CqlVarintBorrowed<'b>,
559 scale: i32,
560}
561
562impl CqlDecimal {
564 pub fn from_signed_be_bytes_and_exponent(bytes: Vec<u8>, scale: i32) -> Self {
569 Self {
570 int_val: CqlVarint::from_signed_bytes_be(bytes),
571 scale,
572 }
573 }
574
575 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &[u8], scale: i32) -> Self {
580 Self::from_signed_be_bytes_and_exponent(bytes.to_vec(), scale)
581 }
582}
583
584impl<'b> CqlDecimalBorrowed<'b> {
586 pub fn from_signed_be_bytes_slice_and_exponent(bytes: &'b [u8], scale: i32) -> Self {
591 Self {
592 int_val: CqlVarintBorrowed::from_signed_bytes_be_slice(bytes),
593 scale,
594 }
595 }
596}
597
598impl CqlDecimal {
600 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
603 (self.int_val.as_signed_bytes_be_slice(), self.scale)
604 }
605
606 pub fn into_signed_be_bytes_and_exponent(self) -> (Vec<u8>, i32) {
609 (self.int_val.into_signed_bytes_be(), self.scale)
610 }
611}
612
613impl CqlDecimalBorrowed<'_> {
615 pub fn as_signed_be_bytes_slice_and_exponent(&self) -> (&[u8], i32) {
618 (self.int_val.as_signed_bytes_be_slice(), self.scale)
619 }
620}
621
622#[cfg(feature = "bigdecimal-04")]
623impl From<CqlDecimal> for bigdecimal_04::BigDecimal {
624 fn from(value: CqlDecimal) -> Self {
625 Self::from((
626 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
627 value.int_val.as_signed_bytes_be_slice(),
628 ),
629 value.scale as i64,
630 ))
631 }
632}
633
634#[cfg(feature = "bigdecimal-04")]
635impl From<CqlDecimalBorrowed<'_>> for bigdecimal_04::BigDecimal {
636 fn from(value: CqlDecimalBorrowed) -> Self {
637 Self::from((
638 bigdecimal_04::num_bigint::BigInt::from_signed_bytes_be(
639 value.int_val.as_signed_bytes_be_slice(),
640 ),
641 value.scale as i64,
642 ))
643 }
644}
645
646#[cfg(feature = "bigdecimal-04")]
647impl TryFrom<bigdecimal_04::BigDecimal> for CqlDecimal {
648 type Error = <i64 as TryInto<i32>>::Error;
649
650 fn try_from(value: bigdecimal_04::BigDecimal) -> Result<Self, Self::Error> {
651 let (bigint, scale) = value.into_bigint_and_exponent();
652 let bytes = bigint.to_signed_bytes_be();
653 Ok(Self::from_signed_be_bytes_and_exponent(
654 bytes,
655 scale.try_into()?,
656 ))
657 }
658}
659
660#[derive(Clone, Copy, PartialEq, Eq, Debug)]
664pub struct CqlDate(pub u32);
665
666#[derive(Clone, Copy, PartialEq, Eq, Debug)]
670pub struct CqlTimestamp(pub i64);
671
672#[derive(Clone, Copy, PartialEq, Eq, Debug)]
676pub struct CqlTime(pub i64);
677
678impl CqlDate {
679 fn try_to_chrono_04_naive_date(&self) -> Result<chrono_04::NaiveDate, ValueOverflow> {
680 let days_since_unix_epoch = self.0 as i64 - (1 << 31);
681
682 let duration_since_unix_epoch =
685 chrono_04::Duration::try_days(days_since_unix_epoch).unwrap();
686
687 chrono_04::NaiveDate::from_yo_opt(1970, 1)
688 .unwrap()
689 .checked_add_signed(duration_since_unix_epoch)
690 .ok_or(ValueOverflow)
691 }
692}
693
694#[cfg(feature = "chrono-04")]
695impl From<chrono_04::NaiveDate> for CqlDate {
696 fn from(value: chrono_04::NaiveDate) -> Self {
697 let unix_epoch = chrono_04::NaiveDate::from_yo_opt(1970, 1).unwrap();
698
699 let days = ((1 << 31) + value.signed_duration_since(unix_epoch).num_days()) as u32;
702
703 Self(days)
704 }
705}
706
707#[cfg(feature = "chrono-04")]
708impl TryInto<chrono_04::NaiveDate> for CqlDate {
709 type Error = ValueOverflow;
710
711 fn try_into(self) -> Result<chrono_04::NaiveDate, Self::Error> {
712 self.try_to_chrono_04_naive_date()
713 }
714}
715
716impl CqlTimestamp {
717 fn try_to_chrono_04_datetime_utc(
718 &self,
719 ) -> Result<chrono_04::DateTime<chrono_04::Utc>, ValueOverflow> {
720 use chrono_04::TimeZone;
721 match chrono_04::Utc.timestamp_millis_opt(self.0) {
722 chrono_04::LocalResult::Single(datetime) => Ok(datetime),
723 _ => Err(ValueOverflow),
724 }
725 }
726}
727
728#[cfg(feature = "chrono-04")]
729impl From<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
730 fn from(value: chrono_04::DateTime<chrono_04::Utc>) -> Self {
731 Self(value.timestamp_millis())
732 }
733}
734
735#[cfg(feature = "chrono-04")]
736impl TryInto<chrono_04::DateTime<chrono_04::Utc>> for CqlTimestamp {
737 type Error = ValueOverflow;
738
739 fn try_into(self) -> Result<chrono_04::DateTime<chrono_04::Utc>, Self::Error> {
740 self.try_to_chrono_04_datetime_utc()
741 }
742}
743
744#[cfg(feature = "chrono-04")]
745impl TryFrom<chrono_04::NaiveTime> for CqlTime {
746 type Error = ValueOverflow;
747
748 fn try_from(value: chrono_04::NaiveTime) -> Result<Self, Self::Error> {
749 let nanos = value
750 .signed_duration_since(chrono_04::NaiveTime::MIN)
751 .num_nanoseconds()
752 .unwrap();
753
754 if nanos <= 86399999999999 {
756 Ok(Self(nanos))
757 } else {
758 Err(ValueOverflow)
759 }
760 }
761}
762
763#[cfg(feature = "chrono-04")]
764impl TryInto<chrono_04::NaiveTime> for CqlTime {
765 type Error = ValueOverflow;
766
767 fn try_into(self) -> Result<chrono_04::NaiveTime, Self::Error> {
768 let secs = (self.0 / 1_000_000_000)
769 .try_into()
770 .map_err(|_| ValueOverflow)?;
771 let nanos = (self.0 % 1_000_000_000)
772 .try_into()
773 .map_err(|_| ValueOverflow)?;
774 chrono_04::NaiveTime::from_num_seconds_from_midnight_opt(secs, nanos).ok_or(ValueOverflow)
775 }
776}
777
778#[cfg(feature = "time-03")]
779impl From<time_03::Date> for CqlDate {
780 fn from(value: time_03::Date) -> Self {
781 const JULIAN_DAY_OFFSET: i64 =
782 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
783
784 const _: () = assert!(
786 time_03::Date::MAX.to_julian_day() as i64 + JULIAN_DAY_OFFSET < u32::MAX as i64
787 );
788 const _: () = assert!(
789 time_03::Date::MIN.to_julian_day() as i64 + JULIAN_DAY_OFFSET > u32::MIN as i64
790 );
791
792 let days = value.to_julian_day() as i64 + JULIAN_DAY_OFFSET;
793
794 Self(days as u32)
795 }
796}
797
798#[cfg(feature = "time-03")]
799impl TryInto<time_03::Date> for CqlDate {
800 type Error = ValueOverflow;
801
802 fn try_into(self) -> Result<time_03::Date, Self::Error> {
803 const JULIAN_DAY_OFFSET: i64 =
804 (1 << 31) - time_03::OffsetDateTime::UNIX_EPOCH.date().to_julian_day() as i64;
805
806 let julian_days = (self.0 as i64 - JULIAN_DAY_OFFSET)
807 .try_into()
808 .map_err(|_| ValueOverflow)?;
809
810 time_03::Date::from_julian_day(julian_days).map_err(|_| ValueOverflow)
811 }
812}
813
814#[cfg(feature = "time-03")]
815impl From<time_03::OffsetDateTime> for CqlTimestamp {
816 fn from(value: time_03::OffsetDateTime) -> Self {
817 const _: () = assert!(
820 time_03::PrimitiveDateTime::MAX
821 .assume_utc()
822 .unix_timestamp_nanos()
823 / 1_000_000
825 < i64::MAX as i128
826 );
827 const _: () = assert!(
828 time_03::PrimitiveDateTime::MIN
829 .assume_utc()
830 .unix_timestamp_nanos()
831 / 1_000_000
832 > i64::MIN as i128
833 );
834
835 Self(value.unix_timestamp() * 1000 + value.millisecond() as i64)
837 }
838}
839
840#[cfg(feature = "time-03")]
841impl TryInto<time_03::OffsetDateTime> for CqlTimestamp {
842 type Error = ValueOverflow;
843
844 fn try_into(self) -> Result<time_03::OffsetDateTime, Self::Error> {
845 time_03::OffsetDateTime::from_unix_timestamp_nanos(self.0 as i128 * 1_000_000)
846 .map_err(|_| ValueOverflow)
847 }
848}
849
850#[cfg(feature = "time-03")]
851impl From<time_03::Time> for CqlTime {
852 fn from(value: time_03::Time) -> Self {
853 let (h, m, s, n) = value.as_hms_nano();
854
855 let nanos = (h as i64 * 3600 + m as i64 * 60 + s as i64) * 1_000_000_000 + n as i64;
857
858 Self(nanos)
859 }
860}
861
862#[cfg(feature = "time-03")]
863impl TryInto<time_03::Time> for CqlTime {
864 type Error = ValueOverflow;
865
866 fn try_into(self) -> Result<time_03::Time, Self::Error> {
867 let h = self.0 / 3_600_000_000_000;
868 let m = self.0 / 60_000_000_000 % 60;
869 let s = self.0 / 1_000_000_000 % 60;
870 let n = self.0 % 1_000_000_000;
871
872 time_03::Time::from_hms_nano(
873 h.try_into().map_err(|_| ValueOverflow)?,
874 m as u8,
875 s as u8,
876 n as u32,
877 )
878 .map_err(|_| ValueOverflow)
879 }
880}
881
882#[derive(Clone, Debug, Copy, PartialEq, Eq)]
884pub struct CqlDuration {
885 pub months: i32,
887 pub days: i32,
889 pub nanoseconds: i64,
891}
892
893#[derive(Clone, Debug, PartialEq)]
899#[non_exhaustive]
900pub enum CqlValue {
901 Ascii(String),
903 Boolean(bool),
905 Blob(Vec<u8>),
907 Counter(Counter),
909 Decimal(CqlDecimal),
911 Date(CqlDate),
914 Double(f64),
916 Duration(CqlDuration),
918 Empty,
920 Float(f32),
922 Int(i32),
924 BigInt(i64),
926 Text(String),
928 Timestamp(CqlTimestamp),
930 Inet(IpAddr),
932 List(Vec<CqlValue>),
934 Map(Vec<(CqlValue, CqlValue)>),
937 Set(Vec<CqlValue>),
939 UserDefinedType {
943 keyspace: String,
945 name: String,
947 fields: Vec<(String, Option<CqlValue>)>,
949 },
950 SmallInt(i16),
952 TinyInt(i8),
954 Time(CqlTime),
956 Timeuuid(CqlTimeuuid),
958 Tuple(Vec<Option<CqlValue>>),
961 Uuid(Uuid),
963 Varint(CqlVarint),
965 Vector(Vec<CqlValue>),
968}
969
970impl CqlValue {
971 pub fn as_ascii(&self) -> Option<&String> {
973 match self {
974 Self::Ascii(s) => Some(s),
975 _ => None,
976 }
977 }
978
979 pub fn as_cql_date(&self) -> Option<CqlDate> {
981 match self {
982 Self::Date(d) => Some(*d),
983 _ => None,
984 }
985 }
986
987 #[cfg(test)]
989 #[cfg(feature = "chrono-04")]
990 pub(crate) fn as_naive_date_04(&self) -> Option<chrono_04::NaiveDate> {
991 self.as_cql_date().and_then(|date| date.try_into().ok())
992 }
993
994 #[cfg(test)]
996 #[cfg(feature = "time-03")]
997 pub(crate) fn as_date_03(&self) -> Option<time_03::Date> {
998 self.as_cql_date().and_then(|date| date.try_into().ok())
999 }
1000
1001 pub fn as_cql_timestamp(&self) -> Option<CqlTimestamp> {
1003 match self {
1004 Self::Timestamp(i) => Some(*i),
1005 _ => None,
1006 }
1007 }
1008
1009 #[cfg(test)]
1011 #[cfg(feature = "chrono-04")]
1012 pub(crate) fn as_datetime_04(&self) -> Option<chrono_04::DateTime<chrono_04::Utc>> {
1013 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
1014 }
1015
1016 #[cfg(test)]
1018 #[cfg(feature = "time-03")]
1019 pub(crate) fn as_offset_date_time_03(&self) -> Option<time_03::OffsetDateTime> {
1020 self.as_cql_timestamp().and_then(|ts| ts.try_into().ok())
1021 }
1022
1023 pub fn as_cql_time(&self) -> Option<CqlTime> {
1025 match self {
1026 Self::Time(i) => Some(*i),
1027 _ => None,
1028 }
1029 }
1030
1031 #[cfg(test)]
1033 #[cfg(feature = "chrono-04")]
1034 pub(crate) fn as_naive_time_04(&self) -> Option<chrono_04::NaiveTime> {
1035 self.as_cql_time().and_then(|ts| ts.try_into().ok())
1036 }
1037
1038 #[cfg(test)]
1040 #[cfg(feature = "time-03")]
1041 pub(crate) fn as_time_03(&self) -> Option<time_03::Time> {
1042 self.as_cql_time().and_then(|ts| ts.try_into().ok())
1043 }
1044
1045 pub fn as_cql_duration(&self) -> Option<CqlDuration> {
1047 match self {
1048 Self::Duration(i) => Some(*i),
1049 _ => None,
1050 }
1051 }
1052
1053 pub fn as_counter(&self) -> Option<Counter> {
1055 match self {
1056 Self::Counter(i) => Some(*i),
1057 _ => None,
1058 }
1059 }
1060
1061 pub fn as_boolean(&self) -> Option<bool> {
1063 match self {
1064 Self::Boolean(i) => Some(*i),
1065 _ => None,
1066 }
1067 }
1068
1069 pub fn as_double(&self) -> Option<f64> {
1071 match self {
1072 Self::Double(d) => Some(*d),
1073 _ => None,
1074 }
1075 }
1076
1077 pub fn as_uuid(&self) -> Option<Uuid> {
1079 match self {
1080 Self::Uuid(u) => Some(*u),
1081 _ => None,
1082 }
1083 }
1084
1085 pub fn as_float(&self) -> Option<f32> {
1087 match self {
1088 Self::Float(f) => Some(*f),
1089 _ => None,
1090 }
1091 }
1092
1093 pub fn as_int(&self) -> Option<i32> {
1095 match self {
1096 Self::Int(i) => Some(*i),
1097 _ => None,
1098 }
1099 }
1100
1101 pub fn as_bigint(&self) -> Option<i64> {
1103 match self {
1104 Self::BigInt(i) => Some(*i),
1105 _ => None,
1106 }
1107 }
1108
1109 pub fn as_tinyint(&self) -> Option<i8> {
1111 match self {
1112 Self::TinyInt(i) => Some(*i),
1113 _ => None,
1114 }
1115 }
1116
1117 pub fn as_smallint(&self) -> Option<i16> {
1119 match self {
1120 Self::SmallInt(i) => Some(*i),
1121 _ => None,
1122 }
1123 }
1124
1125 pub fn as_blob(&self) -> Option<&Vec<u8>> {
1127 match self {
1128 Self::Blob(v) => Some(v),
1129 _ => None,
1130 }
1131 }
1132
1133 pub fn as_text(&self) -> Option<&String> {
1135 match self {
1136 Self::Text(s) => Some(s),
1137 _ => None,
1138 }
1139 }
1140
1141 pub fn as_timeuuid(&self) -> Option<CqlTimeuuid> {
1143 match self {
1144 Self::Timeuuid(u) => Some(*u),
1145 _ => None,
1146 }
1147 }
1148
1149 pub fn into_string(self) -> Option<String> {
1151 match self {
1152 Self::Ascii(s) => Some(s),
1153 Self::Text(s) => Some(s),
1154 _ => None,
1155 }
1156 }
1157
1158 pub fn into_blob(self) -> Option<Vec<u8>> {
1160 match self {
1161 Self::Blob(b) => Some(b),
1162 _ => None,
1163 }
1164 }
1165
1166 pub fn as_inet(&self) -> Option<IpAddr> {
1168 match self {
1169 Self::Inet(a) => Some(*a),
1170 _ => None,
1171 }
1172 }
1173
1174 pub fn as_list(&self) -> Option<&Vec<CqlValue>> {
1176 match self {
1177 Self::List(s) => Some(s),
1178 _ => None,
1179 }
1180 }
1181
1182 pub fn as_set(&self) -> Option<&Vec<CqlValue>> {
1184 match self {
1185 Self::Set(s) => Some(s),
1186 _ => None,
1187 }
1188 }
1189
1190 pub fn as_map(&self) -> Option<&Vec<(CqlValue, CqlValue)>> {
1193 match self {
1194 Self::Map(s) => Some(s),
1195 _ => None,
1196 }
1197 }
1198
1199 pub fn as_udt(&self) -> Option<&Vec<(String, Option<CqlValue>)>> {
1203 match self {
1204 Self::UserDefinedType { fields, .. } => Some(fields),
1205 _ => None,
1206 }
1207 }
1208
1209 pub fn into_vec(self) -> Option<Vec<CqlValue>> {
1211 match self {
1212 Self::List(s) => Some(s),
1213 Self::Set(s) => Some(s),
1214 _ => None,
1215 }
1216 }
1217
1218 pub fn into_pair_vec(self) -> Option<Vec<(CqlValue, CqlValue)>> {
1221 match self {
1222 Self::Map(s) => Some(s),
1223 _ => None,
1224 }
1225 }
1226
1227 pub fn into_udt_pair_vec(self) -> Option<Vec<(String, Option<CqlValue>)>> {
1230 match self {
1231 Self::UserDefinedType { fields, .. } => Some(fields),
1232 _ => None,
1233 }
1234 }
1235
1236 pub fn into_cql_varint(self) -> Option<CqlVarint> {
1238 match self {
1239 Self::Varint(i) => Some(i),
1240 _ => None,
1241 }
1242 }
1243
1244 pub fn into_cql_decimal(self) -> Option<CqlDecimal> {
1246 match self {
1247 Self::Decimal(i) => Some(i),
1248 _ => None,
1249 }
1250 }
1251 }
1253
1254impl std::fmt::Display for CqlValue {
1257 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1258 use crate::pretty::{
1259 CqlStringLiteralDisplayer, HexBytes, MaybeNullDisplayer, PairDisplayer,
1260 };
1261
1262 match self {
1263 CqlValue::Ascii(a) => write!(f, "{}", CqlStringLiteralDisplayer(a))?,
1265 CqlValue::Text(t) => write!(f, "{}", CqlStringLiteralDisplayer(t))?,
1266 CqlValue::Blob(b) => write!(f, "0x{:x}", HexBytes(b))?,
1267 CqlValue::Empty => write!(f, "0x")?,
1268 CqlValue::Decimal(d) => {
1269 let (bytes, scale) = d.as_signed_be_bytes_slice_and_exponent();
1270 write!(
1271 f,
1272 "blobAsDecimal(0x{:x}{:x})",
1273 HexBytes(&scale.to_be_bytes()),
1274 HexBytes(bytes)
1275 )?
1276 }
1277 CqlValue::Float(fl) => write!(f, "{fl}")?,
1278 CqlValue::Double(d) => write!(f, "{d}")?,
1279 CqlValue::Boolean(b) => write!(f, "{b}")?,
1280 CqlValue::Int(i) => write!(f, "{i}")?,
1281 CqlValue::BigInt(bi) => write!(f, "{bi}")?,
1282 CqlValue::Inet(i) => write!(f, "'{i}'")?,
1283 CqlValue::SmallInt(si) => write!(f, "{si}")?,
1284 CqlValue::TinyInt(ti) => write!(f, "{ti}")?,
1285 CqlValue::Varint(vi) => write!(
1286 f,
1287 "blobAsVarint(0x{:x})",
1288 HexBytes(vi.as_signed_bytes_be_slice())
1289 )?,
1290 CqlValue::Counter(c) => write!(f, "{}", c.0)?,
1291 CqlValue::Date(d) => {
1292 match d.try_to_chrono_04_naive_date() {
1295 Ok(d) => write!(f, "'{d}'")?,
1296 Err(_) => f.write_str("<date out of representable range>")?,
1297 }
1298 }
1299 CqlValue::Duration(d) => write!(f, "{}mo{}d{}ns", d.months, d.days, d.nanoseconds)?,
1300 CqlValue::Time(CqlTime(t)) => {
1301 write!(
1302 f,
1303 "'{:02}:{:02}:{:02}.{:09}'",
1304 t / 3_600_000_000_000,
1305 t / 60_000_000_000 % 60,
1306 t / 1_000_000_000 % 60,
1307 t % 1_000_000_000,
1308 )?;
1309 }
1310 CqlValue::Timestamp(ts) => match ts.try_to_chrono_04_datetime_utc() {
1311 Ok(d) => write!(f, "{}", d.format("'%Y-%m-%d %H:%M:%S%.3f%z'"))?,
1312 Err(_) => f.write_str("<timestamp out of representable range>")?,
1313 },
1314 CqlValue::Timeuuid(t) => write!(f, "{t}")?,
1315 CqlValue::Uuid(u) => write!(f, "{u}")?,
1316
1317 CqlValue::Tuple(t) => {
1319 f.write_str("(")?;
1320 t.iter()
1321 .map(|x| MaybeNullDisplayer(x.as_ref()))
1322 .safe_format(",")
1323 .fmt(f)?;
1324 f.write_str(")")?;
1325 }
1326 CqlValue::List(v) | CqlValue::Vector(v) => {
1327 f.write_str("[")?;
1328 v.iter().safe_format(",").fmt(f)?;
1329 f.write_str("]")?;
1330 }
1331 CqlValue::Set(v) => {
1332 f.write_str("{")?;
1333 v.iter().safe_format(",").fmt(f)?;
1334 f.write_str("}")?;
1335 }
1336 CqlValue::Map(m) => {
1337 f.write_str("{")?;
1338 m.iter()
1339 .map(|(k, v)| PairDisplayer(k, v))
1340 .safe_format(",")
1341 .fmt(f)?;
1342 f.write_str("}")?;
1343 }
1344 CqlValue::UserDefinedType {
1345 keyspace: _,
1346 name: _,
1347 fields,
1348 } => {
1349 f.write_str("{")?;
1350 fields
1351 .iter()
1352 .map(|(k, v)| PairDisplayer(k, MaybeNullDisplayer(v.as_ref())))
1353 .safe_format(",")
1354 .fmt(f)?;
1355 f.write_str("}")?;
1356 }
1357 }
1358 Ok(())
1359 }
1360}
1361
1362pub fn deser_cql_value(
1364 typ: &ColumnType,
1365 buf: &mut &[u8],
1366) -> StdResult<CqlValue, DeserializationError> {
1367 use crate::frame::response::result::ColumnType::*;
1368 use crate::frame::response::result::NativeType::*;
1369
1370 if buf.is_empty() {
1371 match typ {
1372 Native(Ascii) | Native(Blob) | Native(Text) => {
1373 }
1375 _ => return Ok(CqlValue::Empty),
1376 }
1377 }
1378 let v = Some(FrameSlice::new_borrowed(buf));
1383
1384 Ok(match typ {
1385 Native(Ascii) => {
1386 let s = String::deserialize(typ, v)?;
1387 CqlValue::Ascii(s)
1388 }
1389 Native(Boolean) => {
1390 let b = bool::deserialize(typ, v)?;
1391 CqlValue::Boolean(b)
1392 }
1393 Native(Blob) => {
1394 let b = Vec::<u8>::deserialize(typ, v)?;
1395 CqlValue::Blob(b)
1396 }
1397 Native(Date) => {
1398 let d = CqlDate::deserialize(typ, v)?;
1399 CqlValue::Date(d)
1400 }
1401 Native(Counter) => {
1402 let c = crate::value::Counter::deserialize(typ, v)?;
1403 CqlValue::Counter(c)
1404 }
1405 Native(Decimal) => {
1406 let d = CqlDecimal::deserialize(typ, v)?;
1407 CqlValue::Decimal(d)
1408 }
1409 Native(Double) => {
1410 let d = f64::deserialize(typ, v)?;
1411 CqlValue::Double(d)
1412 }
1413 Native(Float) => {
1414 let f = f32::deserialize(typ, v)?;
1415 CqlValue::Float(f)
1416 }
1417 Native(Int) => {
1418 let i = i32::deserialize(typ, v)?;
1419 CqlValue::Int(i)
1420 }
1421 Native(SmallInt) => {
1422 let si = i16::deserialize(typ, v)?;
1423 CqlValue::SmallInt(si)
1424 }
1425 Native(TinyInt) => {
1426 let ti = i8::deserialize(typ, v)?;
1427 CqlValue::TinyInt(ti)
1428 }
1429 Native(BigInt) => {
1430 let bi = i64::deserialize(typ, v)?;
1431 CqlValue::BigInt(bi)
1432 }
1433 Native(Text) => {
1434 let s = String::deserialize(typ, v)?;
1435 CqlValue::Text(s)
1436 }
1437 Native(Timestamp) => {
1438 let t = CqlTimestamp::deserialize(typ, v)?;
1439 CqlValue::Timestamp(t)
1440 }
1441 Native(Time) => {
1442 let t = CqlTime::deserialize(typ, v)?;
1443 CqlValue::Time(t)
1444 }
1445 Native(Timeuuid) => {
1446 let t = CqlTimeuuid::deserialize(typ, v)?;
1447 CqlValue::Timeuuid(t)
1448 }
1449 Native(Duration) => {
1450 let d = CqlDuration::deserialize(typ, v)?;
1451 CqlValue::Duration(d)
1452 }
1453 Native(Inet) => {
1454 let i = IpAddr::deserialize(typ, v)?;
1455 CqlValue::Inet(i)
1456 }
1457 Native(Uuid) => {
1458 let uuid = uuid::Uuid::deserialize(typ, v)?;
1459 CqlValue::Uuid(uuid)
1460 }
1461 Native(Varint) => {
1462 let vi = CqlVarint::deserialize(typ, v)?;
1463 CqlValue::Varint(vi)
1464 }
1465 Collection {
1466 typ: CollectionType::List(_type_name),
1467 ..
1468 } => {
1469 let l = Vec::<CqlValue>::deserialize(typ, v)?;
1470 CqlValue::List(l)
1471 }
1472 Collection {
1473 typ: CollectionType::Map(_key_type, _value_type),
1474 ..
1475 } => {
1476 let iter = MapIterator::<'_, '_, CqlValue, CqlValue>::deserialize(typ, v)?;
1477 let m: Vec<(CqlValue, CqlValue)> = iter.collect::<StdResult<_, _>>()?;
1478 CqlValue::Map(m)
1479 }
1480 Collection {
1481 typ: CollectionType::Set(_type_name),
1482 ..
1483 } => {
1484 let s = Vec::<CqlValue>::deserialize(typ, v)?;
1485 CqlValue::Set(s)
1486 }
1487 Vector { .. } => {
1488 let iter = VectorIterator::deserialize(typ, v)?;
1489 let v: Vec<CqlValue> = iter.collect::<StdResult<_, _>>()?;
1490 CqlValue::Vector(v)
1491 }
1492 UserDefinedType {
1493 definition: udt, ..
1494 } => {
1495 let iter = UdtIterator::deserialize(typ, v)?;
1496 let fields: Vec<(String, Option<CqlValue>)> = iter
1497 .map(|((col_name, col_type), res)| {
1498 res.and_then(|v| {
1499 let val = Option::<CqlValue>::deserialize(col_type, v.flatten())?;
1500 Ok((col_name.clone().into_owned(), val))
1501 })
1502 })
1503 .collect::<StdResult<_, _>>()?;
1504
1505 CqlValue::UserDefinedType {
1506 keyspace: udt.keyspace.clone().into_owned(),
1507 name: udt.name.clone().into_owned(),
1508 fields,
1509 }
1510 }
1511 Tuple(type_names) => {
1512 let t = type_names
1513 .iter()
1514 .map(|typ| -> StdResult<_, DeserializationError> {
1515 let raw = types::read_bytes_opt(buf).map_err(|e| {
1516 mk_deser_err::<CqlValue>(
1517 typ,
1518 BuiltinDeserializationErrorKind::RawCqlBytesReadError(e),
1519 )
1520 })?;
1521 raw.map(|v| CqlValue::deserialize(typ, Some(FrameSlice::new_borrowed(v))))
1522 .transpose()
1523 })
1524 .collect::<StdResult<_, _>>()?;
1525 CqlValue::Tuple(t)
1526 }
1527 })
1528}
1529
1530#[derive(Debug, Default, PartialEq)]
1541pub struct Row {
1542 pub columns: Vec<Option<CqlValue>>,
1546}
1547
1548#[cfg(test)]
1549mod tests {
1550 use std::str::FromStr as _;
1551
1552 use super::*;
1553
1554 #[test]
1555 fn timeuuid_msb_byte_order() {
1556 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1557
1558 assert_eq!(0x0607040500010203, uuid.msb());
1559 }
1560
1561 #[test]
1562 fn timeuuid_msb_clears_version_bits() {
1563 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1565
1566 assert_eq!(0x0fffffffffffffff, uuid.msb());
1567 }
1568
1569 #[test]
1570 fn timeuuid_lsb_byte_order() {
1571 let uuid = CqlTimeuuid::from_str("00010203-0405-0607-0809-0a0b0c0d0e0f").unwrap();
1572
1573 assert_eq!(0x08090a0b0c0d0e0f, uuid.lsb());
1574 }
1575
1576 #[test]
1577 fn timeuuid_lsb_modifies_no_bits() {
1578 let uuid = CqlTimeuuid::from_str("ffffffff-ffff-ffff-ffff-ffffffffffff").unwrap();
1579
1580 assert_eq!(0xffffffffffffffff, uuid.lsb());
1581 }
1582
1583 #[test]
1584 fn timeuuid_nil() {
1585 let uuid = CqlTimeuuid::nil();
1586
1587 assert_eq!(0x0000000000000000, uuid.msb());
1588 assert_eq!(0x0000000000000000, uuid.lsb());
1589 }
1590
1591 #[test]
1592 fn test_cql_value_displayer() {
1593 assert_eq!(format!("{}", CqlValue::Boolean(true)), "true");
1594 assert_eq!(format!("{}", CqlValue::Int(123)), "123");
1595 assert_eq!(
1596 format!(
1597 "{}",
1598 CqlValue::Decimal(CqlDecimal::from_signed_be_bytes_and_exponent(
1600 vec![0x01, 0xE2, 0x40],
1601 3
1602 ))
1603 ),
1604 "blobAsDecimal(0x0000000301e240)"
1605 );
1606 assert_eq!(format!("{}", CqlValue::Float(12.75)), "12.75");
1607 assert_eq!(
1608 format!("{}", CqlValue::Text("Ala ma kota".to_owned())),
1609 "'Ala ma kota'"
1610 );
1611 assert_eq!(
1612 format!("{}", CqlValue::Text("Foo's".to_owned())),
1613 "'Foo''s'"
1614 );
1615
1616 assert_eq!(
1618 format!("{}", CqlValue::Date(CqlDate(40 + (1 << 31)))),
1619 "'1970-02-10'"
1620 );
1621 assert_eq!(
1622 format!(
1623 "{}",
1624 CqlValue::Duration(CqlDuration {
1625 months: 1,
1626 days: 2,
1627 nanoseconds: 3,
1628 })
1629 ),
1630 "1mo2d3ns"
1631 );
1632 let t = chrono_04::NaiveTime::from_hms_nano_opt(6, 5, 4, 123)
1633 .unwrap()
1634 .signed_duration_since(chrono_04::NaiveTime::MIN);
1635 let t = t.num_nanoseconds().unwrap();
1636 assert_eq!(
1637 format!("{}", CqlValue::Time(CqlTime(t))),
1638 "'06:05:04.000000123'"
1639 );
1640
1641 let t = chrono_04::NaiveDate::from_ymd_opt(2005, 4, 2)
1642 .unwrap()
1643 .and_time(chrono_04::NaiveTime::from_hms_opt(19, 37, 42).unwrap());
1644 assert_eq!(
1645 format!(
1646 "{}",
1647 CqlValue::Timestamp(CqlTimestamp(
1648 t.signed_duration_since(chrono_04::NaiveDateTime::default())
1649 .num_milliseconds()
1650 ))
1651 ),
1652 "'2005-04-02 19:37:42.000+0000'"
1653 );
1654
1655 let list_or_set = vec![CqlValue::Int(1), CqlValue::Int(3), CqlValue::Int(2)];
1657 assert_eq!(
1658 format!("{}", CqlValue::List(list_or_set.clone())),
1659 "[1,3,2]"
1660 );
1661 assert_eq!(format!("{}", CqlValue::Set(list_or_set.clone())), "{1,3,2}");
1662
1663 let tuple: Vec<_> = list_or_set
1664 .into_iter()
1665 .map(Some)
1666 .chain(std::iter::once(None))
1667 .collect();
1668 assert_eq!(format!("{}", CqlValue::Tuple(tuple)), "(1,3,2,null)");
1669
1670 let map = vec![
1671 (CqlValue::Text("foo".to_owned()), CqlValue::Int(123)),
1672 (CqlValue::Text("bar".to_owned()), CqlValue::Int(321)),
1673 ];
1674 assert_eq!(format!("{}", CqlValue::Map(map)), "{'foo':123,'bar':321}");
1675
1676 let fields = vec![
1677 ("foo".to_owned(), Some(CqlValue::Int(123))),
1678 ("bar".to_owned(), Some(CqlValue::Int(321))),
1679 ];
1680 assert_eq!(
1681 format!(
1682 "{}",
1683 CqlValue::UserDefinedType {
1684 keyspace: "ks".to_owned(),
1685 name: "typ".to_owned(),
1686 fields,
1687 }
1688 ),
1689 "{foo:123,bar:321}"
1690 );
1691 }
1692}