@@ -22,10 +22,9 @@ use bytes::{Buf, Bytes, BytesMut};
2222use nom:: Parser ;
2323use nom:: {
2424 IResult ,
25- bytes:: streaming:: { take, take_while1} ,
26- character:: streaming:: { char, digit1, line_ending, not_line_ending, space1} ,
27- combinator:: { map, map_res, opt, recognize} ,
28- multi:: separated_list0,
25+ bytes:: streaming:: take,
26+ character:: streaming:: { char, digit1, line_ending, not_line_ending} ,
27+ combinator:: { map_res, opt, recognize} ,
2928 sequence:: terminated,
3029} ;
3130
@@ -106,17 +105,13 @@ impl RespParse {
106105 }
107106
108107 fn parse_inline ( input : & [ u8 ] ) -> IResult < & [ u8 ] , RespData > {
109- let mut parse_parts = separated_list0 (
110- space1,
111- map (
112- take_while1 ( |c| c != b' ' && c != b'\r' && c != b'\n' ) ,
113- |s : & [ u8 ] | Bytes :: copy_from_slice ( s) ,
114- ) ,
115- ) ;
116-
117- let ( input, parts) = parse_parts. parse ( input) ?;
108+ let ( input, line) = terminated ( not_line_ending, line_ending) . parse ( input) ?;
118109
119- let ( input, _) = line_ending ( input) ?;
110+ let parts = line
111+ . split ( |byte| byte. is_ascii_whitespace ( ) )
112+ . filter ( |part| !part. is_empty ( ) )
113+ . map ( Bytes :: copy_from_slice)
114+ . collect :: < Vec < _ > > ( ) ;
120115
121116 if parts. is_empty ( ) {
122117 return Err ( nom:: Err :: Error ( nom:: error:: Error :: new (
@@ -125,7 +120,27 @@ impl RespParse {
125120 ) ) ) ;
126121 }
127122
128- Ok ( ( input, RespData :: Inline ( parts) ) )
123+ Ok ( (
124+ input,
125+ RespData :: Array ( Some (
126+ parts
127+ . into_iter ( )
128+ . map ( |part| RespData :: BulkString ( Some ( part) ) )
129+ . collect ( ) ,
130+ ) ) ,
131+ ) )
132+ }
133+
134+ fn skip_empty_lines ( & mut self ) {
135+ loop {
136+ if self . buffer . starts_with ( b"\r \n " ) {
137+ self . buffer . advance ( 2 ) ;
138+ } else if self . buffer . starts_with ( b"\n " ) {
139+ self . buffer . advance ( 1 ) ;
140+ } else {
141+ break ;
142+ }
143+ }
129144 }
130145
131146 fn parse_simple_string ( input : & [ u8 ] ) -> IResult < & [ u8 ] , RespData > {
@@ -432,6 +447,8 @@ impl RespParse {
432447 }
433448
434449 fn process_buffer ( & mut self ) -> RespParseResult {
450+ self . skip_empty_lines ( ) ;
451+
435452 if self . buffer . is_empty ( ) {
436453 return RespParseResult :: Incomplete ;
437454 }
@@ -497,6 +514,8 @@ impl Drop for RespParse {
497514#[ allow( clippy:: unwrap_used) ]
498515#[ cfg( test) ]
499516mod tests {
517+ use crate :: command:: CommandType ;
518+
500519 use super :: Bytes ;
501520 use super :: { Parse , RespData , RespParse , RespParseResult , RespVersion } ;
502521
@@ -533,52 +552,111 @@ mod tests {
533552 let res = parser. parse ( Bytes :: from ( "ping\r \n " ) ) ;
534553 assert_eq ! (
535554 res,
536- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "ping" ) ] ) )
555+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
556+ Bytes :: from( "ping" ) ,
557+ ) ) ] ) ) )
537558 ) ;
538559 parser. reset ( ) ;
539560
540561 let res = parser. parse ( Bytes :: from ( "PING\r \n \r \n " ) ) ;
541562 assert_eq ! (
542563 res,
543- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "PING" ) ] ) )
564+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
565+ Bytes :: from( "PING" ) ,
566+ ) ) ] ) ) )
544567 ) ;
545568 parser. reset ( ) ;
546569
547570 let res = parser. parse ( Bytes :: from ( "PING\n " ) ) ;
548571 assert_eq ! (
549572 res,
550- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "PING" ) ] ) )
573+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
574+ Bytes :: from( "PING" ) ,
575+ ) ) ] ) ) )
551576 ) ;
552577 parser. reset ( ) ;
553578
554579 let res = parser. parse ( Bytes :: from ( "PING\n \n " ) ) ;
555580 assert_eq ! (
556581 res,
557- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "PING" ) ] ) )
582+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
583+ Bytes :: from( "PING" ) ,
584+ ) ) ] ) ) )
558585 ) ;
559586 parser. reset ( ) ;
560587
561588 let res = parser. parse ( Bytes :: from ( "PING\r \n \n " ) ) ;
562589 assert_eq ! (
563590 res,
564- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "PING" ) ] ) )
591+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
592+ Bytes :: from( "PING" ) ,
593+ ) ) ] ) ) )
565594 ) ;
566595 parser. reset ( ) ;
567596 }
568597
598+ #[ test]
599+ fn test_parse_inline_info_command ( ) {
600+ let mut parser = RespParse :: new ( RespVersion :: RESP2 ) ;
601+ let res = parser. parse ( Bytes :: from ( "info\r \n " ) ) ;
602+ assert_eq ! (
603+ res,
604+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
605+ Bytes :: from( "info" ) ,
606+ ) ) ] ) ) )
607+ ) ;
608+
609+ let command = parser. next_command ( ) . unwrap ( ) . unwrap ( ) ;
610+ assert_eq ! ( command. command_type, CommandType :: Info ) ;
611+ assert ! ( command. args. is_empty( ) ) ;
612+ }
613+
614+ #[ test]
615+ fn test_parse_inline_command_with_args ( ) {
616+ let mut parser = RespParse :: new ( RespVersion :: RESP2 ) ;
617+ let res = parser. parse ( Bytes :: from ( "ping hello\r \n " ) ) ;
618+ assert_eq ! (
619+ res,
620+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![
621+ RespData :: BulkString ( Some ( Bytes :: from( "ping" ) ) ) ,
622+ RespData :: BulkString ( Some ( Bytes :: from( "hello" ) ) ) ,
623+ ] ) ) )
624+ ) ;
625+
626+ let command = parser. next_command ( ) . unwrap ( ) . unwrap ( ) ;
627+ assert_eq ! ( command. command_type, CommandType :: Ping ) ;
628+ assert_eq ! ( command. arg_count( ) , 1 ) ;
629+ assert_eq ! ( command. arg( 0 ) , Some ( & Bytes :: from( "hello" ) ) ) ;
630+ }
631+
632+ #[ test]
633+ fn test_parse_inline_with_surrounding_whitespace ( ) {
634+ let mut parser = RespParse :: new ( RespVersion :: RESP2 ) ;
635+ let res = parser. parse ( Bytes :: from ( " \t info \t \r \n " ) ) ;
636+ assert_eq ! (
637+ res,
638+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
639+ Bytes :: from( "info" ) ,
640+ ) ) ] ) ) )
641+ ) ;
642+
643+ let command = parser. next_command ( ) . unwrap ( ) . unwrap ( ) ;
644+ assert_eq ! ( command. command_type, CommandType :: Info ) ;
645+ }
646+
569647 #[ test]
570648 fn test_parse_inline_params ( ) {
571649 let mut parser = RespParse :: new ( RespVersion :: RESP2 ) ;
572650 let res = parser. parse ( Bytes :: from ( "hmget fruit apple banana watermelon\r \n " ) ) ;
573651 assert_eq ! (
574652 res,
575- RespParseResult :: Complete ( RespData :: Inline ( vec![
576- Bytes :: from( "hmget" ) ,
577- Bytes :: from( "fruit" ) ,
578- Bytes :: from( "apple" ) ,
579- Bytes :: from( "banana" ) ,
580- Bytes :: from( "watermelon" )
581- ] ) )
653+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![
654+ RespData :: BulkString ( Some ( Bytes :: from( "hmget" ) ) ) ,
655+ RespData :: BulkString ( Some ( Bytes :: from( "fruit" ) ) ) ,
656+ RespData :: BulkString ( Some ( Bytes :: from( "apple" ) ) ) ,
657+ RespData :: BulkString ( Some ( Bytes :: from( "banana" ) ) ) ,
658+ RespData :: BulkString ( Some ( Bytes :: from( "watermelon" ) ) ) ,
659+ ] ) ) )
582660 ) ;
583661 }
584662
@@ -591,20 +669,49 @@ mod tests {
591669 ) ) ;
592670 assert_eq ! (
593671 res,
594- RespParseResult :: Complete ( RespData :: Inline ( vec![ Bytes :: from( "ping" ) ] ) )
672+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
673+ Bytes :: from( "ping" ) ,
674+ ) ) ] ) ) )
595675 ) ;
596676
597677 let res = parser. parse ( Bytes :: new ( ) ) ;
598678 assert_eq ! (
599679 res,
600- RespParseResult :: Complete ( RespData :: Inline ( vec![
601- Bytes :: from( "hmget" ) ,
602- Bytes :: from( "fruit" ) ,
603- Bytes :: from( "apple" ) ,
604- Bytes :: from( "banana" ) ,
605- Bytes :: from( "watermelon" )
606- ] ) )
680+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![
681+ RespData :: BulkString ( Some ( Bytes :: from( "hmget" ) ) ) ,
682+ RespData :: BulkString ( Some ( Bytes :: from( "fruit" ) ) ) ,
683+ RespData :: BulkString ( Some ( Bytes :: from( "apple" ) ) ) ,
684+ RespData :: BulkString ( Some ( Bytes :: from( "banana" ) ) ) ,
685+ RespData :: BulkString ( Some ( Bytes :: from( "watermelon" ) ) ) ,
686+ ] ) ) )
687+ ) ;
688+ }
689+
690+ #[ test]
691+ fn test_parse_multiple_inline_with_blank_lines ( ) {
692+ let mut parser = RespParse :: new ( RespVersion :: RESP2 ) ;
693+
694+ let res = parser. parse ( Bytes :: from ( "ping\r \n \r \n info\r \n " ) ) ;
695+ assert_eq ! (
696+ res,
697+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
698+ Bytes :: from( "ping" ) ,
699+ ) ) ] ) ) )
607700 ) ;
701+
702+ let res = parser. parse ( Bytes :: new ( ) ) ;
703+ assert_eq ! (
704+ res,
705+ RespParseResult :: Complete ( RespData :: Array ( Some ( vec![ RespData :: BulkString ( Some (
706+ Bytes :: from( "info" ) ,
707+ ) ) ] ) ) )
708+ ) ;
709+
710+ let command = parser. next_command ( ) . unwrap ( ) . unwrap ( ) ;
711+ assert_eq ! ( command. command_type, CommandType :: Ping ) ;
712+
713+ let command = parser. next_command ( ) . unwrap ( ) . unwrap ( ) ;
714+ assert_eq ! ( command. command_type, CommandType :: Info ) ;
608715 }
609716
610717 #[ test]
0 commit comments