Skip to content

Commit 802e683

Browse files
committed
result/deser_cql_value: use DeserializeValue impls
In the future, we will probably deprecate and remove `deser_cql_value` altogether. For now, let's make it at least less bloaty. To reduce code duplication, `deser_cql_value()` now uses DeserializeValue impls for nearly all of the deserialized types. Two notable exceptions are: 1. CQL Map - because it is represented as Vec<(CqlValue, CqlValue)> in CqlValue, and Vec<T> is only deserializable from CQL Set|Map. Therefore, MapIterator is deserialized using its DeserializeValue impl, and then collected into Vec. 2. CQL Tuple - because it is represented in CqlValue much differently than in DeserializeValue impls: Vec<CqlValue> vs (T1, T2, ..., Tn). Therefore, it's similarly to how it was before, just style is changed from imperative to iterator-based, and DeserializeValue impl is called instead of `deser_cql_value` there. As a bonus, we get more descriptive error messages (as compared to old `ParseError::BadIncomingData` ones).
1 parent 58f523f commit 802e683

File tree

3 files changed

+123
-213
lines changed

3 files changed

+123
-213
lines changed

scylla-cql/src/frame/response/result.rs

Lines changed: 88 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
use crate::cql_to_rust::{FromRow, FromRowError};
22
use crate::frame::response::event::SchemaChangeEvent;
3-
use crate::frame::types::vint_decode;
43
use crate::frame::value::{
54
Counter, CqlDate, CqlDecimal, CqlDuration, CqlTime, CqlTimestamp, CqlTimeuuid, CqlVarint,
65
};
76
use crate::frame::{frame_errors::ParseError, types};
8-
use byteorder::{BigEndian, ReadBytesExt};
7+
use crate::types::deserialize::value::{DeserializeValue, MapIterator, UdtIterator};
8+
use crate::types::deserialize::FrameSlice;
99
use bytes::{Buf, Bytes};
1010
use std::borrow::Cow;
11-
use std::{
12-
convert::{TryFrom, TryInto},
13-
net::IpAddr,
14-
result::Result as StdResult,
15-
str,
16-
};
11+
use std::{convert::TryInto, net::IpAddr, result::Result as StdResult, str};
1712
use uuid::Uuid;
1813

1914
#[cfg(feature = "chrono")]
@@ -655,6 +650,11 @@ pub fn deser_cql_value(typ: &ColumnType, buf: &mut &[u8]) -> StdResult<CqlValue,
655650
_ => return Ok(CqlValue::Empty),
656651
}
657652
}
653+
// The `new_borrowed` version of FrameSlice is deficient in that it does not hold
654+
// a `Bytes` reference to the frame, only a slice.
655+
// This is not a problem here, fortunately, because none of CqlValue variants contain
656+
// any `Bytes` - only exclusively owned types - so we never call FrameSlice::to_bytes().
657+
let v = Some(FrameSlice::new_borrowed(buf));
658658

659659
Ok(match typ {
660660
Custom(type_str) => {
@@ -664,239 +664,112 @@ pub fn deser_cql_value(typ: &ColumnType, buf: &mut &[u8]) -> StdResult<CqlValue,
664664
)));
665665
}
666666
Ascii => {
667-
if !buf.is_ascii() {
668-
return Err(ParseError::BadIncomingData(
669-
"String is not ascii!".to_string(),
670-
));
671-
}
672-
CqlValue::Ascii(str::from_utf8(buf)?.to_owned())
667+
let s = String::deserialize(typ, v)?;
668+
CqlValue::Ascii(s)
673669
}
674670
Boolean => {
675-
if buf.len() != 1 {
676-
return Err(ParseError::BadIncomingData(format!(
677-
"Buffer length should be 1 not {}",
678-
buf.len()
679-
)));
680-
}
681-
CqlValue::Boolean(buf[0] != 0x00)
671+
let b = bool::deserialize(typ, v)?;
672+
CqlValue::Boolean(b)
673+
}
674+
Blob => {
675+
let b = Vec::<u8>::deserialize(typ, v)?;
676+
CqlValue::Blob(b)
682677
}
683-
Blob => CqlValue::Blob(buf.to_vec()),
684678
Date => {
685-
if buf.len() != 4 {
686-
return Err(ParseError::BadIncomingData(format!(
687-
"Buffer length should be 4 not {}",
688-
buf.len()
689-
)));
690-
}
691-
692-
let date_value = buf.read_u32::<BigEndian>()?;
693-
CqlValue::Date(CqlDate(date_value))
679+
let d = CqlDate::deserialize(typ, v)?;
680+
CqlValue::Date(d)
694681
}
695682
Counter => {
696-
if buf.len() != 8 {
697-
return Err(ParseError::BadIncomingData(format!(
698-
"Buffer length should be 8 not {}",
699-
buf.len()
700-
)));
701-
}
702-
CqlValue::Counter(crate::frame::value::Counter(buf.read_i64::<BigEndian>()?))
683+
let c = crate::frame::response::result::Counter::deserialize(typ, v)?;
684+
CqlValue::Counter(c)
703685
}
704686
Decimal => {
705-
let scale = types::read_int(buf)?;
706-
let bytes = buf.to_vec();
707-
let big_decimal: CqlDecimal =
708-
CqlDecimal::from_signed_be_bytes_and_exponent(bytes, scale);
709-
710-
CqlValue::Decimal(big_decimal)
687+
let d = CqlDecimal::deserialize(typ, v)?;
688+
CqlValue::Decimal(d)
711689
}
712690
Double => {
713-
if buf.len() != 8 {
714-
return Err(ParseError::BadIncomingData(format!(
715-
"Buffer length should be 8 not {}",
716-
buf.len()
717-
)));
718-
}
719-
CqlValue::Double(buf.read_f64::<BigEndian>()?)
691+
let d = f64::deserialize(typ, v)?;
692+
CqlValue::Double(d)
720693
}
721694
Float => {
722-
if buf.len() != 4 {
723-
return Err(ParseError::BadIncomingData(format!(
724-
"Buffer length should be 4 not {}",
725-
buf.len()
726-
)));
727-
}
728-
CqlValue::Float(buf.read_f32::<BigEndian>()?)
695+
let f = f32::deserialize(typ, v)?;
696+
CqlValue::Float(f)
729697
}
730698
Int => {
731-
if buf.len() != 4 {
732-
return Err(ParseError::BadIncomingData(format!(
733-
"Buffer length should be 4 not {}",
734-
buf.len()
735-
)));
736-
}
737-
CqlValue::Int(buf.read_i32::<BigEndian>()?)
699+
let i = i32::deserialize(typ, v)?;
700+
CqlValue::Int(i)
738701
}
739702
SmallInt => {
740-
if buf.len() != 2 {
741-
return Err(ParseError::BadIncomingData(format!(
742-
"Buffer length should be 2 not {}",
743-
buf.len()
744-
)));
745-
}
746-
747-
CqlValue::SmallInt(buf.read_i16::<BigEndian>()?)
703+
let si = i16::deserialize(typ, v)?;
704+
CqlValue::SmallInt(si)
748705
}
749706
TinyInt => {
750-
if buf.len() != 1 {
751-
return Err(ParseError::BadIncomingData(format!(
752-
"Buffer length should be 1 not {}",
753-
buf.len()
754-
)));
755-
}
756-
CqlValue::TinyInt(buf.read_i8()?)
707+
let ti = i8::deserialize(typ, v)?;
708+
CqlValue::TinyInt(ti)
757709
}
758710
BigInt => {
759-
if buf.len() != 8 {
760-
return Err(ParseError::BadIncomingData(format!(
761-
"Buffer length should be 8 not {}",
762-
buf.len()
763-
)));
764-
}
765-
CqlValue::BigInt(buf.read_i64::<BigEndian>()?)
711+
let bi = i64::deserialize(typ, v)?;
712+
CqlValue::BigInt(bi)
713+
}
714+
Text => {
715+
let s = String::deserialize(typ, v)?;
716+
CqlValue::Text(s)
766717
}
767-
Text => CqlValue::Text(str::from_utf8(buf)?.to_owned()),
768718
Timestamp => {
769-
if buf.len() != 8 {
770-
return Err(ParseError::BadIncomingData(format!(
771-
"Buffer length should be 8 not {}",
772-
buf.len()
773-
)));
774-
}
775-
let millis = buf.read_i64::<BigEndian>()?;
776-
777-
CqlValue::Timestamp(CqlTimestamp(millis))
719+
let t = CqlTimestamp::deserialize(typ, v)?;
720+
CqlValue::Timestamp(t)
778721
}
779722
Time => {
780-
if buf.len() != 8 {
781-
return Err(ParseError::BadIncomingData(format!(
782-
"Buffer length should be 8 not {}",
783-
buf.len()
784-
)));
785-
}
786-
let nanoseconds: i64 = buf.read_i64::<BigEndian>()?;
787-
788-
// Valid values are in the range 0 to 86399999999999
789-
if !(0..=86399999999999).contains(&nanoseconds) {
790-
return Err(ParseError::BadIncomingData(format! {
791-
"Invalid time value only 0 to 86399999999999 allowed: {}.", nanoseconds
792-
}));
793-
}
794-
795-
CqlValue::Time(CqlTime(nanoseconds))
723+
let t = CqlTime::deserialize(typ, v)?;
724+
CqlValue::Time(t)
796725
}
797726
Timeuuid => {
798-
if buf.len() != 16 {
799-
return Err(ParseError::BadIncomingData(format!(
800-
"Buffer length should be 16 not {}",
801-
buf.len()
802-
)));
803-
}
804-
let uuid = uuid::Uuid::from_slice(buf).expect("Deserializing Uuid failed.");
805-
CqlValue::Timeuuid(CqlTimeuuid::from(uuid))
727+
let t = CqlTimeuuid::deserialize(typ, v)?;
728+
CqlValue::Timeuuid(t)
806729
}
807730
Duration => {
808-
let months = i32::try_from(vint_decode(buf)?)?;
809-
let days = i32::try_from(vint_decode(buf)?)?;
810-
let nanoseconds = vint_decode(buf)?;
811-
812-
CqlValue::Duration(CqlDuration {
813-
months,
814-
days,
815-
nanoseconds,
816-
})
731+
let d = CqlDuration::deserialize(typ, v)?;
732+
CqlValue::Duration(d)
733+
}
734+
Inet => {
735+
let i = IpAddr::deserialize(typ, v)?;
736+
CqlValue::Inet(i)
817737
}
818-
Inet => CqlValue::Inet(match buf.len() {
819-
4 => {
820-
let ret = IpAddr::from(<[u8; 4]>::try_from(&buf[0..4])?);
821-
buf.advance(4);
822-
ret
823-
}
824-
16 => {
825-
let ret = IpAddr::from(<[u8; 16]>::try_from(&buf[0..16])?);
826-
buf.advance(16);
827-
ret
828-
}
829-
v => {
830-
return Err(ParseError::BadIncomingData(format!(
831-
"Invalid inet bytes length: {}",
832-
v
833-
)));
834-
}
835-
}),
836738
Uuid => {
837-
if buf.len() != 16 {
838-
return Err(ParseError::BadIncomingData(format!(
839-
"Buffer length should be 16 not {}",
840-
buf.len()
841-
)));
842-
}
843-
let uuid = uuid::Uuid::from_slice(buf).expect("Deserializing Uuid failed.");
739+
let uuid = uuid::Uuid::deserialize(typ, v)?;
844740
CqlValue::Uuid(uuid)
845741
}
846-
Varint => CqlValue::Varint(CqlVarint::from_signed_bytes_be(buf.to_vec())),
847-
List(type_name) => {
848-
let len: usize = types::read_int(buf)?.try_into()?;
849-
let mut res = Vec::with_capacity(len);
850-
for _ in 0..len {
851-
let mut b = types::read_bytes(buf)?;
852-
res.push(deser_cql_value(type_name, &mut b)?);
853-
}
854-
CqlValue::List(res)
742+
Varint => {
743+
let vi = CqlVarint::deserialize(typ, v)?;
744+
CqlValue::Varint(vi)
855745
}
856-
Map(key_type, value_type) => {
857-
let len: usize = types::read_int(buf)?.try_into()?;
858-
let mut res = Vec::with_capacity(len);
859-
for _ in 0..len {
860-
let mut b = types::read_bytes(buf)?;
861-
let key = deser_cql_value(key_type, &mut b)?;
862-
b = types::read_bytes(buf)?;
863-
let val = deser_cql_value(value_type, &mut b)?;
864-
res.push((key, val));
865-
}
866-
CqlValue::Map(res)
746+
List(_type_name) => {
747+
let l = Vec::<CqlValue>::deserialize(typ, v)?;
748+
CqlValue::List(l)
867749
}
868-
Set(type_name) => {
869-
let len: usize = types::read_int(buf)?.try_into()?;
870-
let mut res = Vec::with_capacity(len);
871-
for _ in 0..len {
872-
// TODO: is `null` allowed as set element? Should we use read_bytes_opt?
873-
let mut b = types::read_bytes(buf)?;
874-
res.push(deser_cql_value(type_name, &mut b)?);
875-
}
876-
CqlValue::Set(res)
750+
Map(_key_type, _value_type) => {
751+
let iter = MapIterator::<'_, CqlValue, CqlValue>::deserialize(typ, v)?;
752+
let m: Vec<(CqlValue, CqlValue)> = iter.collect::<StdResult<_, _>>()?;
753+
CqlValue::Map(m)
754+
}
755+
Set(_type_name) => {
756+
let s = Vec::<CqlValue>::deserialize(typ, v)?;
757+
CqlValue::Set(s)
877758
}
878759
UserDefinedType {
879760
type_name,
880761
keyspace,
881-
field_types,
762+
..
882763
} => {
883-
let mut fields: Vec<(String, Option<CqlValue>)> = Vec::new();
884-
885-
for (field_name, field_type) in field_types {
886-
// If a field is added to a UDT and we read an old (frozen ?) version of it,
887-
// the driver will fail to parse the whole UDT.
888-
// This is why we break the parsing after we reach the end of the serialized UDT.
889-
if buf.is_empty() {
890-
break;
891-
}
892-
893-
let mut field_value: Option<CqlValue> = None;
894-
if let Some(mut field_val_bytes) = types::read_bytes_opt(buf)? {
895-
field_value = Some(deser_cql_value(field_type, &mut field_val_bytes)?);
896-
}
897-
898-
fields.push((field_name.clone(), field_value));
899-
}
764+
let iter = UdtIterator::deserialize(typ, v)?;
765+
let fields: Vec<(String, Option<CqlValue>)> = iter
766+
.map(|((col_name, col_type), res)| {
767+
res.and_then(|v| {
768+
let val = Option::<CqlValue>::deserialize(col_type, v.flatten())?;
769+
Ok((col_name.clone(), val))
770+
})
771+
})
772+
.collect::<StdResult<_, _>>()?;
900773

901774
CqlValue::UserDefinedType {
902775
keyspace: keyspace.clone(),
@@ -905,15 +778,19 @@ pub fn deser_cql_value(typ: &ColumnType, buf: &mut &[u8]) -> StdResult<CqlValue,
905778
}
906779
}
907780
Tuple(type_names) => {
908-
let mut res = Vec::with_capacity(type_names.len());
909-
for type_name in type_names {
910-
match types::read_bytes_opt(buf)? {
911-
Some(mut b) => res.push(Some(deser_cql_value(type_name, &mut b)?)),
912-
None => res.push(None),
913-
};
914-
}
915-
916-
CqlValue::Tuple(res)
781+
let t = type_names
782+
.iter()
783+
.map(|typ| {
784+
types::read_bytes_opt(buf).and_then(|v| {
785+
v.map(|v| {
786+
CqlValue::deserialize(typ, Some(FrameSlice::new_borrowed(v)))
787+
.map_err(Into::into)
788+
})
789+
.transpose()
790+
})
791+
})
792+
.collect::<StdResult<_, _>>()?;
793+
CqlValue::Tuple(t)
917794
}
918795
})
919796
}

0 commit comments

Comments
 (0)