1+ use bytes:: Bytes ;
12use itertools:: Itertools ;
23use lazy_static:: lazy_static;
3- use scylla_cql:: cql_to_rust:: FromCqlVal ;
4- use scylla_cql:: frame:: response:: result:: { deser_cql_value, ColumnType , TableSpec } ;
5- use scylla_cql:: types:: deserialize:: DeserializationError ;
4+ use scylla_cql:: frame:: response:: result:: { ColumnType , TableSpec } ;
5+ use scylla_cql:: types:: deserialize:: value:: ListlikeIterator ;
6+ use scylla_cql:: types:: deserialize:: {
7+ DeserializationError , DeserializeValue , FrameSlice , TypeCheckError ,
8+ } ;
69use thiserror:: Error ;
710use tracing:: warn;
811use uuid:: Uuid ;
@@ -11,12 +14,15 @@ use crate::routing::{Shard, Token};
1114use crate :: transport:: Node ;
1215
1316use std:: collections:: { HashMap , HashSet } ;
17+ use std:: ops:: Deref ;
1418use std:: sync:: Arc ;
1519
1620#[ derive( Error , Debug ) ]
1721pub ( crate ) enum TabletParsingError {
1822 #[ error( transparent) ]
1923 Deserialization ( #[ from] DeserializationError ) ,
24+ #[ error( transparent) ]
25+ TypeCheck ( #[ from] TypeCheckError ) ,
2026 #[ error( "Shard id for tablet is negative: {0}" ) ]
2127 ShardNum ( i32 ) ,
2228}
@@ -35,7 +41,8 @@ pub(crate) struct RawTablet {
3541 replicas : RawTabletReplicas ,
3642}
3743
38- type RawTabletPayload = ( i64 , i64 , Vec < ( Uuid , i32 ) > ) ;
44+ type RawTabletPayload < ' frame , ' metadata > =
45+ ( i64 , i64 , ListlikeIterator < ' frame , ' metadata , ( Uuid , i32 ) > ) ;
3946
4047lazy_static ! {
4148 static ref RAW_TABLETS_CQL_TYPE : ColumnType <' static > = ColumnType :: Tuple ( vec![
@@ -52,29 +59,37 @@ const CUSTOM_PAYLOAD_TABLETS_V1_KEY: &str = "tablets-routing-v1";
5259
5360impl RawTablet {
5461 pub ( crate ) fn from_custom_payload (
55- payload : & HashMap < String , Vec < u8 > > ,
62+ payload : & HashMap < String , Bytes > ,
5663 ) -> Option < Result < RawTablet , TabletParsingError > > {
5764 let payload = payload. get ( CUSTOM_PAYLOAD_TABLETS_V1_KEY ) ?;
58- let cql_value = match deser_cql_value ( & RAW_TABLETS_CQL_TYPE , & mut payload. as_slice ( ) ) {
59- Ok ( r) => r,
60- Err ( e) => return Some ( Err ( e. into ( ) ) ) ,
65+
66+ if let Err ( err) =
67+ <RawTabletPayload as DeserializeValue < ' _ , ' _ > >:: type_check ( RAW_TABLETS_CQL_TYPE . deref ( ) )
68+ {
69+ return Some ( Err ( err. into ( ) ) ) ;
6170 } ;
6271
63- // This could only fail if the type was wrong, but we do pass correct type
64- // to `deser_cql_value`.
6572 let ( first_token, last_token, replicas) : RawTabletPayload =
66- FromCqlVal :: from_cql ( cql_value) . unwrap ( ) ;
73+ match <RawTabletPayload as DeserializeValue < ' _ , ' _ > >:: deserialize (
74+ RAW_TABLETS_CQL_TYPE . deref ( ) ,
75+ Some ( FrameSlice :: new ( payload) ) ,
76+ ) {
77+ Ok ( tuple) => tuple,
78+ Err ( err) => return Some ( Err ( err. into ( ) ) ) ,
79+ } ;
6780
6881 let replicas = match replicas
69- . into_iter ( )
70- . map ( |( uuid, shard_num) | match shard_num. try_into ( ) {
71- Ok ( s) => Ok ( ( uuid, s) ) ,
72- Err ( _) => Err ( shard_num) ,
82+ . map ( |res| {
83+ res. map_err ( TabletParsingError :: from)
84+ . and_then ( |( uuid, shard_num) | match shard_num. try_into ( ) {
85+ Ok ( s) => Ok ( ( uuid, s) ) ,
86+ Err ( _) => Err ( TabletParsingError :: ShardNum ( shard_num) ) ,
87+ } )
7388 } )
74- . collect :: < Result < Vec < ( Uuid , Shard ) > , _ > > ( )
89+ . collect :: < Result < Vec < ( Uuid , Shard ) > , TabletParsingError > > ( )
7590 {
7691 Ok ( r) => r,
77- Err ( shard_num ) => return Some ( Err ( TabletParsingError :: ShardNum ( shard_num ) ) ) ,
92+ Err ( err ) => return Some ( Err ( err ) ) ,
7893 } ;
7994
8095 Some ( Ok ( RawTablet {
@@ -590,6 +605,7 @@ mod tests {
590605 use std:: collections:: { HashMap , HashSet } ;
591606 use std:: sync:: Arc ;
592607
608+ use bytes:: Bytes ;
593609 use scylla_cql:: frame:: response:: result:: { ColumnType , CqlValue , TableSpec } ;
594610 use scylla_cql:: types:: serialize:: value:: SerializeValue ;
595611 use scylla_cql:: types:: serialize:: CellWriter ;
@@ -618,8 +634,10 @@ mod tests {
618634
619635 #[ test]
620636 fn test_raw_tablet_deser_trash ( ) {
621- let custom_payload =
622- HashMap :: from ( [ ( CUSTOM_PAYLOAD_TABLETS_V1_KEY . to_string ( ) , vec ! [ 1 , 2 , 3 ] ) ] ) ;
637+ let custom_payload = HashMap :: from ( [ (
638+ CUSTOM_PAYLOAD_TABLETS_V1_KEY . to_string ( ) ,
639+ Bytes :: from_static ( & [ 1 , 2 , 3 ] ) ,
640+ ) ] ) ;
623641 assert_matches:: assert_matches!(
624642 RawTablet :: from_custom_payload( & custom_payload) ,
625643 Some ( Err ( TabletParsingError :: Deserialization ( _) ) )
@@ -648,7 +666,7 @@ mod tests {
648666 SerializeValue :: serialize ( & value, & col_type, CellWriter :: new ( & mut data) ) . unwrap ( ) ;
649667 debug ! ( "{:?}" , data) ;
650668
651- custom_payload. insert ( CUSTOM_PAYLOAD_TABLETS_V1_KEY . to_string ( ) , data) ;
669+ custom_payload. insert ( CUSTOM_PAYLOAD_TABLETS_V1_KEY . to_string ( ) , Bytes :: from ( data) ) ;
652670
653671 assert_matches:: assert_matches!(
654672 RawTablet :: from_custom_payload( & custom_payload) ,
@@ -688,7 +706,7 @@ mod tests {
688706 // Skipping length because `SerializeValue::serialize` adds length at the
689707 // start of serialized value while Scylla sends the value without initial
690708 // length.
691- data[ 4 ..] . to_vec ( ) ,
709+ Bytes :: copy_from_slice ( & data[ 4 ..] ) ,
692710 ) ;
693711
694712 let tablet = RawTablet :: from_custom_payload ( & custom_payload)
0 commit comments