@@ -603,15 +603,64 @@ fn decode_bytes(buf: &mut BytesMut, idx: usize) -> DecodeResult {
603
603
}
604
604
}
605
605
606
+ fn is_array_ready_to_decode (
607
+ buf : & mut BytesMut ,
608
+ idx : usize ,
609
+ array_size : usize ,
610
+ ) -> Result < ( bool , usize ) , Error > {
611
+ let mut items: usize = 0 ;
612
+ let mut pos = idx;
613
+
614
+ // counting beginning of array items in buffer by `\r\n<type>`
615
+ loop {
616
+ let Some ( new_pos) = buf[ pos..] . windows ( 2 ) . position ( |w| w. starts_with ( b"\r \n " ) ) else {
617
+ break ;
618
+ } ;
619
+
620
+ if pos + new_pos + 2 >= buf. len ( ) {
621
+ break ;
622
+ }
623
+ pos += new_pos + 2 ;
624
+
625
+ items += match & buf[ pos] {
626
+ // check nested array and calc it as item
627
+ b'*' => match decode_length ( buf, pos) {
628
+ Ok ( Some ( ( _, -1 ) ) ) => 1 ,
629
+ Ok ( Some ( ( p, size) ) ) if size >= 0 => {
630
+ let ( ready, end_of_scan) = is_array_ready_to_decode ( buf, p, size as usize ) ?;
631
+ // nested array isn't ready
632
+ if !ready {
633
+ return Ok ( ( false , end_of_scan) ) ;
634
+ }
635
+ pos = end_of_scan;
636
+ 1
637
+ }
638
+ Ok ( Some ( ( _, size) ) ) => {
639
+ return Err ( Error :: Parse ( format ! ( "Invalid array size: {}" , size) ) )
640
+ }
641
+ _ => 0 ,
642
+ } ,
643
+ // array item found
644
+ b'$' | b':' | b'+' | b'-' => 1 ,
645
+ _ => 0 ,
646
+ } ;
647
+
648
+ if array_size <= items {
649
+ return Ok ( ( true , pos) ) ;
650
+ }
651
+ }
652
+
653
+ Ok ( ( array_size <= items, pos) )
654
+ }
655
+
606
656
fn decode_array ( buf : & mut BytesMut , idx : usize ) -> DecodeResult {
607
657
match decode_length ( buf, idx) ? {
608
658
Some ( ( pos, -1 ) ) => Ok ( Some ( ( pos, Response :: Nil ) ) ) ,
609
659
Some ( ( pos, size) ) if size >= 0 => {
610
660
let size = size as usize ;
611
661
612
- // ensure all array items present in buffer
613
- let items = buf[ idx..] . windows ( 2 ) . filter ( |w| w == b"\r \n " ) . count ( ) / 2 ;
614
- if items < size {
662
+ let ( is_ready, _) = is_array_ready_to_decode ( buf, idx, size) ?;
663
+ if !is_ready {
615
664
return Ok ( None ) ;
616
665
}
617
666
@@ -767,6 +816,43 @@ mod tests {
767
816
768
817
let deserialized = codec. decode ( & mut bytes) . unwrap ( ) . unwrap ( ) ;
769
818
assert_eq ! ( deserialized, resp) ;
819
+
820
+ // $ echo -e "mget key1 key2\r\nquit" | curl -s telnet://localhost:6379 | python -c "import sys; print(repr(sys.stdin.read()))"
821
+ // '*2\r\n$-1\r\n$-1\r\n+OK\r\n'
822
+ let mut bytes = BytesMut :: copy_from_slice ( b"*2\r \n $-1\r \n $-1\r \n " ) ;
823
+ let result = codec. decode ( & mut bytes) . unwrap ( ) ;
824
+
825
+ assert_eq ! (
826
+ result,
827
+ Some ( Response :: Array ( vec![ Response :: Nil , Response :: Nil ] ) )
828
+ ) ;
829
+
830
+ // uncomplete nested array data
831
+ // [[['a']]]
832
+ // $ echo -e 'eval "return {{{\'a\'}}}" 0\r\nquit' | curl -s telnet://localhost:6379 | python -c "import sys; print(repr(sys.stdin.read()))"
833
+ // '*1\r\n*1\r\n*1\r\n$1\r\na\r\n+OK\r\n'
834
+ let mut bytes = BytesMut :: copy_from_slice ( b"*1\r \n *1\r \n *1\r \n " ) ;
835
+ let result = codec. decode ( & mut bytes) . unwrap ( ) ;
836
+ assert_eq ! ( result, None ) ;
837
+
838
+ // receiving remain parts
839
+ bytes. extend_from_slice ( b"$1\r \n a" ) ;
840
+ let result = codec. decode ( & mut bytes) . unwrap ( ) ;
841
+ assert_eq ! ( result, None ) ;
842
+
843
+ bytes. extend_from_slice ( b"\r " ) ;
844
+ let result = codec. decode ( & mut bytes) . unwrap ( ) ;
845
+ assert_eq ! ( result, None ) ;
846
+
847
+ bytes. extend_from_slice ( b"\n " ) ;
848
+ let result = codec. decode ( & mut bytes) . unwrap ( ) ;
849
+
850
+ assert_eq ! (
851
+ result,
852
+ Some ( Response :: Array ( vec![ Response :: Array ( vec![
853
+ Response :: Array ( vec![ Response :: Bytes ( Bytes :: from_static( b"a" ) ) ] )
854
+ ] ) ] ) )
855
+ ) ;
770
856
}
771
857
772
858
#[ test]
0 commit comments