@@ -18,9 +18,10 @@ const (
1818)
1919
2020var errInvalidMessage = & errProtocol {"invalid message" }
21+ var errIncompletePacket = & errProtocol {"incomplete packet" }
2122
2223// ReadNextCommand reads the next command from the provided packet. It's
23- // possibel that the packet contains multiple commands, or zero commands
24+ // possible that the packet contains multiple commands, or zero commands
2425// when the packet is incomplete.
2526// 'args' is an optional reusable buffer and it can be nil.
2627// 'argsout' are the output arguments for the command. 'kind' is the type of
@@ -31,50 +32,58 @@ var errInvalidMessage = &errProtocol{"invalid message"}
3132func ReadNextCommand (packet []byte , args [][]byte ) (
3233 leftover []byte , argsout [][]byte , kind Kind , stop bool , err error ,
3334) {
35+ args = args [:0 ]
3436 if len (packet ) > 0 {
3537 if packet [0 ] != '*' {
3638 if packet [0 ] == '$' {
3739 return readTile38Command (packet , args )
3840 }
3941 return readTelnetCommand (packet , args )
4042 }
41- for i := 1 ; i < len (packet ); i ++ {
43+ // standard redis command
44+ for s , i := 1 , 1 ; i < len (packet ); i ++ {
4245 if packet [i ] == '\n' {
4346 if packet [i - 1 ] != '\r' {
44- return packet , args , Redis , true , errInvalidMultiBulkLength
47+ println ("here" , i )
48+ return packet , args [:0 ], Redis , true , errInvalidMultiBulkLength
4549 }
46- count , ok := parseInt (packet [1 : i - 1 ])
47- if ! ok || count <= 0 {
48- return packet , args , Redis , true , errInvalidMultiBulkLength
50+ count , ok := parseInt (packet [s : i - 1 ])
51+ if ! ok || count < 0 {
52+ println ("there" , i , count , ok , "[" + string (packet [s :i - 1 ])+ "]" )
53+ return packet , args [:0 ], Redis , true , errInvalidMultiBulkLength
4954 }
5055 i ++
56+ if count == 0 {
57+ return packet [i :], args [:0 ], Redis , i == len (packet ), nil
58+ }
5159 nextArg:
5260 for j := 0 ; j < count ; j ++ {
5361 if i == len (packet ) {
5462 break
5563 }
5664 if packet [i ] != '$' {
57- return packet , args , Redis , true ,
65+ return packet , args [: 0 ] , Redis , true ,
5866 & errProtocol {"expected '$', got '" +
5967 string (packet [i ]) + "'" }
6068 }
6169 for s := i + 1 ; i < len (packet ); i ++ {
6270 if packet [i ] == '\n' {
6371 if packet [i - 1 ] != '\r' {
64- return packet , args , Redis , true , errInvalidBulkLength
72+ return packet , args [: 0 ] , Redis , true , errInvalidBulkLength
6573 }
6674 n , ok := parseInt (packet [s : i - 1 ])
6775 if ! ok || count <= 0 {
68- return packet , args , Redis , true , errInvalidBulkLength
76+ return packet , args [: 0 ] , Redis , true , errInvalidBulkLength
6977 }
7078 i ++
7179 if len (packet )- i >= n + 2 {
7280 if packet [i + n ] != '\r' || packet [i + n + 1 ] != '\n' {
73- return packet , args , Redis , true , errInvalidBulkLength
81+ return packet , args [: 0 ] , Redis , true , errInvalidBulkLength
7482 }
7583 args = append (args , packet [i :i + n ])
7684 i += n + 2
7785 if j == count - 1 {
86+ // done reading
7887 return packet [i :], args , Redis , i == len (packet ), nil
7988 }
8089 continue nextArg
@@ -88,7 +97,7 @@ func ReadNextCommand(packet []byte, args [][]byte) (
8897 }
8998 }
9099 }
91- return packet , args , Redis , true , nil
100+ return packet , args [: 0 ] , Redis , true , errIncompletePacket
92101}
93102
94103func readTile38Command (b []byte , argsbuf [][]byte ) (
@@ -98,12 +107,12 @@ func readTile38Command(b []byte, argsbuf [][]byte) (
98107 if b [i ] == ' ' {
99108 n , ok := parseInt (b [1 :i ])
100109 if ! ok || n < 0 {
101- return b , args , Tile38 , true , errInvalidMessage
110+ return b , args [: 0 ] , Tile38 , true , errInvalidMessage
102111 }
103112 i ++
104113 if len (b ) >= i + n + 2 {
105114 if b [i + n ] != '\r' || b [i + n + 1 ] != '\n' {
106- return b , args , Tile38 , true , errInvalidMessage
115+ return b , args [: 0 ] , Tile38 , true , errInvalidMessage
107116 }
108117 line := b [i : i + n ]
109118 reading:
@@ -143,7 +152,7 @@ func readTile38Command(b []byte, argsbuf [][]byte) (
143152 break
144153 }
145154 }
146- return b , args , Tile38 , true , nil
155+ return b , args [: 0 ] , Tile38 , true , errIncompletePacket
147156}
148157func readTelnetCommand (b []byte , argsbuf [][]byte ) (
149158 leftover []byte , args [][]byte , kind Kind , stop bool , err error ,
@@ -175,7 +184,7 @@ func readTelnetCommand(b []byte, argsbuf [][]byte) (
175184 }
176185 if c == '"' || c == '\'' {
177186 if i != 0 {
178- return b , args , Telnet , true , errUnbalancedQuotes
187+ return b , args [: 0 ] , Telnet , true , errUnbalancedQuotes
179188 }
180189 quotech = c
181190 quote = true
@@ -199,7 +208,7 @@ func readTelnetCommand(b []byte, argsbuf [][]byte) (
199208 args = append (args , nline )
200209 line = line [i + 1 :]
201210 if len (line ) > 0 && line [0 ] != ' ' {
202- return b , args , Telnet , true , errUnbalancedQuotes
211+ return b , args [: 0 ] , Telnet , true , errUnbalancedQuotes
203212 }
204213 continue outer
205214 } else if c == '\\' {
@@ -210,7 +219,7 @@ func readTelnetCommand(b []byte, argsbuf [][]byte) (
210219 nline = append (nline , c )
211220 }
212221 if quote {
213- return b , args , Telnet , true , errUnbalancedQuotes
222+ return b , args [: 0 ] , Telnet , true , errUnbalancedQuotes
214223 }
215224 if len (line ) > 0 {
216225 args = append (args , line )
@@ -220,7 +229,7 @@ func readTelnetCommand(b []byte, argsbuf [][]byte) (
220229 return b [i + 1 :], args , Telnet , i == len (b ), nil
221230 }
222231 }
223- return b , args , Telnet , true , nil
232+ return b , args [: 0 ] , Telnet , true , errIncompletePacket
224233}
225234
226235// AppendUint appends a Redis protocol uint64 to the input bytes.
0 commit comments