1
1
//! Provides types for dealing with CQL value deserialization.
2
2
3
+ use bytes:: Bytes ;
3
4
use std:: {
4
5
collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ,
5
6
hash:: { BuildHasher , Hash } ,
6
7
net:: IpAddr ,
7
8
} ;
8
-
9
- use bytes:: Bytes ;
10
9
use uuid:: Uuid ;
11
10
12
11
use std:: fmt:: { Display , Pointer } ;
@@ -759,7 +758,7 @@ pub struct VectorIterator<'frame, T> {
759
758
}
760
759
761
760
impl < ' frame , T > VectorIterator < ' frame , T > {
762
- fn new (
761
+ pub fn new (
763
762
coll_typ : & ' frame ColumnType ,
764
763
elem_typ : & ' frame ColumnType ,
765
764
count : usize ,
@@ -774,6 +773,54 @@ impl<'frame, T> VectorIterator<'frame, T> {
774
773
phantom_data : std:: marker:: PhantomData ,
775
774
}
776
775
}
776
+
777
+ /// Faster specialization for deserializing a `vector<float>` into `Vec<CqlValue>`.
778
+ /// The generic code `Vec<CqlValue>::deserialize(...)` is much slower because it has to
779
+ /// match on the element type for every item in the vector.
780
+ /// Here we just hardcode `f32` and we can shortcut a lot of code.
781
+ ///
782
+ /// This could be nicer if Rust had generic type specialization in stable,
783
+ /// but for now we need a separate method.
784
+ pub fn deserialize_vector_of_float_to_vec_of_cql_value (
785
+ typ : & ' frame ColumnType ,
786
+ v : Option < FrameSlice < ' frame > > ,
787
+ ) -> Result < Vec < CqlValue > , DeserializationError > {
788
+
789
+ // Typecheck would make sure those never happen:
790
+ let ColumnType :: Vector ( elem_type, elem_count) = typ else {
791
+ panic ! ( "Wrong column type: {:?}. Expected vector<>" , typ) ;
792
+ } ;
793
+ if !matches ! ( elem_type. as_ref( ) , ColumnType :: Float ) {
794
+ panic ! ( "Wrong element type: {:?}. Expected float" , typ) ;
795
+ }
796
+
797
+ let elem_count = * elem_count as usize ;
798
+ let mut frame = v. map ( |s| s. as_slice ( ) ) . unwrap_or_default ( ) ;
799
+
800
+ // Check length only once
801
+ if frame. len ( ) < 4 * elem_count {
802
+ return Err ( mk_deser_err :: < Vec < CqlValue > > (
803
+ typ,
804
+ BuiltinDeserializationErrorKind :: RawCqlBytesReadError (
805
+ LowLevelDeserializationError :: TooFewBytesReceived {
806
+ expected : 4 * elem_count,
807
+ received : frame. len ( ) ,
808
+ } ,
809
+ ) ,
810
+ ) ) ;
811
+ }
812
+
813
+ // We know we have enough elements in the buffer, so now we can skip the checks
814
+ let mut result = Vec :: with_capacity ( elem_count) ;
815
+ for _ in 0 ..elem_count {
816
+ // we did check for frame length earlier so we can safely not check again
817
+ let ( elem, remaining) = unsafe { frame. split_at_unchecked ( 4 ) } ;
818
+ let elem = f32:: from_be_bytes ( elem. try_into ( ) . unwrap ( ) ) ;
819
+ result. push ( CqlValue :: Float ( elem) ) ;
820
+ frame = remaining;
821
+ }
822
+ Ok ( result)
823
+ }
777
824
}
778
825
779
826
impl < ' frame , T > DeserializeValue < ' frame > for VectorIterator < ' frame , T >
@@ -828,6 +875,7 @@ where
828
875
{
829
876
type Item = Result < T , DeserializationError > ;
830
877
878
+ #[ inline]
831
879
fn next ( & mut self ) -> Option < Self :: Item > {
832
880
let raw = self . raw_iter . next ( ) ?. map_err ( |err| {
833
881
mk_deser_err :: < Self > (
@@ -883,6 +931,7 @@ where
883
931
. and_then ( |it| it. collect :: < Result < _ , DeserializationError > > ( ) )
884
932
. map_err ( deser_error_replace_rust_name :: < Self > )
885
933
}
934
+
886
935
ColumnType :: Vector ( _, _) => VectorIterator :: < ' frame , T > :: deserialize ( typ, v)
887
936
. and_then ( |it| it. collect :: < Result < _ , DeserializationError > > ( ) )
888
937
. map_err ( deser_error_replace_rust_name :: < Self > ) ,
@@ -1435,6 +1484,7 @@ impl<'frame> VectorBytesSequenceIterator<'frame> {
1435
1484
impl < ' frame > Iterator for VectorBytesSequenceIterator < ' frame > {
1436
1485
type Item = Result < Option < FrameSlice < ' frame > > , LowLevelDeserializationError > ;
1437
1486
1487
+ #[ inline]
1438
1488
fn next ( & mut self ) -> Option < Self :: Item > {
1439
1489
self . remaining = self . remaining . checked_sub ( 1 ) ?;
1440
1490
Some ( self . slice . read_subslice ( self . elem_len ) )
0 commit comments