8
8
//! simple frames are valid at their creation. We do that because we want to pay the cost of checking
9
9
//! this property only if needed as it is expensive.
10
10
11
- use crate :: frame:: FrameData :: Nested ;
12
- use tokio:: io:: ErrorKind ;
13
- use tokio:: io:: { AsyncBufReadExt , AsyncReadExt , BufReader } ;
11
+ use std:: fmt:: { self , Debug , Display , Formatter } ;
12
+ use tokio:: io:: {
13
+ self , AsyncBufReadExt , AsyncReadExt , AsyncWriteExt , BufReader , BufWriter , ErrorKind ,
14
+ } ;
15
+ use tracing:: error;
14
16
15
17
const CR : u8 = b'\r' ;
16
18
const LF : u8 = b'\n' ;
@@ -20,7 +22,7 @@ const LF: u8 = b'\n';
20
22
/// up front, but we have changed our mind.
21
23
#[ derive( Debug , Clone , Copy , Eq , PartialEq ) ]
22
24
#[ repr( u8 ) ]
23
- pub ( crate ) enum FrameID {
25
+ pub enum FrameID {
24
26
Integer = 58 , // ':'
25
27
// @TODO: remove for now
26
28
// Double = 44, // ','
@@ -89,21 +91,156 @@ enum FrameData {
89
91
Nested ( Vec < Frame > ) ,
90
92
}
91
93
94
+ impl FrameData {
95
+ fn get_integer ( & self ) -> Option < i64 > {
96
+ match self {
97
+ FrameData :: Integer ( value) => Some ( * value) ,
98
+ _ => None ,
99
+ }
100
+ }
101
+ fn get_string ( & self ) -> Option < & String > {
102
+ match self {
103
+ FrameData :: Simple ( value) => Some ( value) ,
104
+ _ => None ,
105
+ }
106
+ }
107
+ fn get_bulk ( & self ) -> Option < ( usize , & String ) > {
108
+ match self {
109
+ FrameData :: Bulk ( size, data) => Some ( ( * size, data) ) ,
110
+ _ => None ,
111
+ }
112
+ }
113
+ fn get_boolean ( & self ) -> Option < bool > {
114
+ match self {
115
+ FrameData :: Boolean ( value) => Some ( * value) ,
116
+ _ => None ,
117
+ }
118
+ }
119
+ pub fn get_nested ( & self ) -> Option < & Vec < Frame > > {
120
+ match self {
121
+ FrameData :: Nested ( value) => Some ( value) ,
122
+ _ => None ,
123
+ }
124
+ }
125
+ }
126
+
92
127
#[ derive( Debug , Eq , PartialEq ) ]
93
- struct Frame {
128
+ pub struct Frame {
94
129
frame_type : FrameID ,
95
130
frame_data : FrameData ,
96
131
}
97
132
98
- fn validate_bool ( data : String ) -> Result < bool , FrameError > {
99
- match data. as_str ( ) {
133
+ impl Frame {
134
+ pub fn get_id ( & self ) -> FrameID {
135
+ self . frame_type
136
+ }
137
+
138
+ pub fn get_array ( & self ) -> Option < & Vec < Frame > > {
139
+ if self . frame_type != FrameID :: Array {
140
+ return None ;
141
+ }
142
+ self . frame_data . get_nested ( )
143
+ }
144
+ pub fn get_bulk ( & self ) -> Option < ( usize , & String ) > {
145
+ match & self . frame_data {
146
+ FrameData :: Bulk ( size, data) => Some ( ( * size, data) ) ,
147
+ _ => None ,
148
+ }
149
+ }
150
+
151
+ pub async fn write_flush_all < T > ( & self , stream : & mut BufWriter < T > ) -> io:: Result < ( ) >
152
+ where
153
+ T : AsyncWriteExt + Unpin ,
154
+ {
155
+ stream. write_all ( self . to_string ( ) . as_bytes ( ) ) . await ?;
156
+ stream. flush ( ) . await
157
+ }
158
+
159
+ pub fn new_bulk_error ( inner : String ) -> Frame {
160
+ Frame {
161
+ frame_type : FrameID :: BulkError ,
162
+ frame_data : FrameData :: Bulk ( inner. len ( ) , inner) ,
163
+ }
164
+ }
165
+
166
+ pub fn new_simple_string ( inner : String ) -> Frame {
167
+ Frame {
168
+ frame_type : FrameID :: SimpleString ,
169
+ frame_data : FrameData :: Simple ( inner) ,
170
+ }
171
+ }
172
+
173
+ pub fn new_bulk_string ( inner : String ) -> Frame {
174
+ Frame {
175
+ frame_type : FrameID :: BulkString ,
176
+ frame_data : FrameData :: Bulk ( inner. len ( ) , inner) ,
177
+ }
178
+ }
179
+
180
+ pub fn new_null ( ) -> Frame {
181
+ Frame {
182
+ frame_type : FrameID :: Null ,
183
+ frame_data : FrameData :: Null ,
184
+ }
185
+ }
186
+ }
187
+
188
+ impl fmt:: Display for Frame {
189
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
190
+ match self . frame_type {
191
+ FrameID :: Integer => {
192
+ let value = self . frame_data . get_integer ( ) . ok_or ( fmt:: Error ) ?;
193
+ write ! ( f, ":{}\r \n " , value)
194
+ }
195
+ FrameID :: SimpleString => {
196
+ let value = self . frame_data . get_string ( ) . ok_or ( fmt:: Error ) ?;
197
+ write ! ( f, "+{}\r \n " , value)
198
+ }
199
+ FrameID :: SimpleError => {
200
+ let value = self . frame_data . get_string ( ) . ok_or ( fmt:: Error ) ?;
201
+ write ! ( f, "-{}\r \n " , value)
202
+ }
203
+ FrameID :: BulkString => {
204
+ let ( len, value) = self . get_bulk ( ) . ok_or ( fmt:: Error ) ?;
205
+ write ! ( f, "${}\r \n {}\r \n " , len, value)
206
+ }
207
+ FrameID :: BulkError => {
208
+ let ( len, value) = self . frame_data . get_bulk ( ) . ok_or ( fmt:: Error ) ?;
209
+ write ! ( f, "!{}\r \n {}\r \n " , len, value)
210
+ }
211
+ FrameID :: Boolean => {
212
+ let value = self . frame_data . get_boolean ( ) . ok_or ( fmt:: Error ) ?;
213
+ let value = if value { "t" } else { "f" } ;
214
+ write ! ( f, "#{}\r \n " , value)
215
+ }
216
+ FrameID :: Null => {
217
+ write ! ( f, "_\r \n " )
218
+ }
219
+ FrameID :: BigNumber => {
220
+ let value = self . frame_data . get_string ( ) . ok_or ( fmt:: Error ) ?;
221
+ write ! ( f, "({}\r \n " , value)
222
+ }
223
+ FrameID :: Array => {
224
+ let frames = self . frame_data . get_nested ( ) . ok_or ( fmt:: Error ) ?;
225
+ write ! ( f, "*{}\r \n " , frames. len( ) ) ?;
226
+ for v in frames {
227
+ write ! ( f, "{}" , v) ?;
228
+ }
229
+ Ok ( ( ) )
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ fn validate_bool ( data : & str ) -> Result < bool , FrameError > {
236
+ match data {
100
237
"t" => Ok ( true ) ,
101
238
"f" => Ok ( false ) ,
102
239
_ => Err ( FrameError :: Invalid ) ,
103
240
}
104
241
}
105
242
106
- async fn decode < T > ( stream : & mut BufReader < T > ) -> Result < Frame , FrameError >
243
+ pub async fn decode < T > ( stream : & mut BufReader < T > ) -> Result < Frame , FrameError >
107
244
where
108
245
T : AsyncReadExt + Unpin ,
109
246
{
@@ -122,7 +259,7 @@ where
122
259
let frame_vec = process_aggregate_frames ( id, stream) . await ?;
123
260
Ok ( Frame {
124
261
frame_type : FrameID :: Array ,
125
- frame_data : Nested ( frame_vec) ,
262
+ frame_data : FrameData :: Nested ( frame_vec) ,
126
263
} )
127
264
}
128
265
}
@@ -138,7 +275,7 @@ where
138
275
let data = read_simple_string ( stream) . await ?;
139
276
match id {
140
277
FrameID :: Boolean => {
141
- let bool = validate_bool ( data) ?;
278
+ let bool = validate_bool ( & data) ?;
142
279
Ok ( Frame {
143
280
frame_type : id,
144
281
frame_data : FrameData :: Boolean ( bool) ,
@@ -189,7 +326,9 @@ where
189
326
T : AsyncReadExt + Unpin ,
190
327
{
191
328
match id {
192
- FrameID :: Array => Err ( FrameError :: Syntax ) ,
329
+ FrameID :: Array => Err ( FrameError :: Syntax (
330
+ "received aggregate frame in non aggregate decoding" . to_string ( ) ,
331
+ ) ) ,
193
332
FrameID :: BulkString | FrameID :: BulkError => process_bulk_frames ( id, stream) . await ,
194
333
_ => process_simple_frames ( id, stream) . await ,
195
334
}
@@ -249,7 +388,7 @@ where
249
388
// to build the right aggregate.
250
389
frames. push ( Frame {
251
390
frame_type : * id,
252
- frame_data : Nested ( last_vec_of_frames) ,
391
+ frame_data : FrameData :: Nested ( last_vec_of_frames) ,
253
392
} ) ;
254
393
* count -= 1 ;
255
394
if * count != 0 {
@@ -269,9 +408,9 @@ pub enum FrameError {
269
408
// Frame is not correctly formatted
270
409
Invalid ,
271
410
// Empty buffer should not be passed to get frame from, so this is an error.
272
- EmptyBuffer ,
411
+ // EmptyBuffer,
273
412
// reached expected EOF
274
- EOF ,
413
+ Eof ,
275
414
// Connection unexpectedly reset
276
415
ConnectionReset ,
277
416
// Unidentified IO error
@@ -281,7 +420,23 @@ pub enum FrameError {
281
420
// Unknown frame type
282
421
Unknown ,
283
422
// This is a programming error. It should not happen.
284
- Syntax ,
423
+ Syntax ( String ) ,
424
+ }
425
+
426
+ impl Display for FrameError {
427
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
428
+ match self {
429
+ FrameError :: Incomplete => write ! ( f, "not enough data to decode a full frame" ) ,
430
+ FrameError :: Invalid => write ! ( f, "frame is not correctly formatted" ) ,
431
+ FrameError :: Eof => write ! ( f, "seen EOF, this is generally a graceful disconnection" ) ,
432
+ FrameError :: ConnectionReset => write ! ( f, "unexpected connection reset" ) ,
433
+ // this error should not happen in practice
434
+ FrameError :: IOError => write ! ( f, "unexpected IO error" ) ,
435
+ FrameError :: UTF8ToInt => write ! ( f, "utf8 to int decoding error" ) ,
436
+ FrameError :: Unknown => write ! ( f, "unable to identify the frame type" ) ,
437
+ FrameError :: Syntax ( message) => write ! ( f, "{}" , message) ,
438
+ }
439
+ }
285
440
}
286
441
287
442
/// `read_simple_string` gets a simple string from the network. As a reminder, such string does
@@ -295,7 +450,7 @@ where
295
450
{
296
451
let mut buf = Vec :: new ( ) ;
297
452
match stream. read_until ( LF , & mut buf) . await {
298
- Ok ( 0 ) => Err ( FrameError :: EOF ) ,
453
+ Ok ( 0 ) => Err ( FrameError :: Eof ) ,
299
454
Ok ( size) => {
300
455
if size < 2 {
301
456
return Err ( FrameError :: Incomplete ) ;
@@ -308,8 +463,10 @@ where
308
463
Ok ( String :: from_utf8_lossy ( & buf[ 0 ..size - 2 ] ) . to_string ( ) )
309
464
}
310
465
Err ( e) if e. kind ( ) == ErrorKind :: ConnectionReset => Err ( FrameError :: ConnectionReset ) ,
311
- // @TODO log e later
312
- Err ( e) => Err ( FrameError :: IOError ) ,
466
+ Err ( e) => {
467
+ error ! ( "unexpected io error: {}" , e) ;
468
+ Err ( FrameError :: IOError )
469
+ }
313
470
}
314
471
}
315
472
@@ -322,7 +479,7 @@ where
322
479
Some ( id) => Ok ( id) ,
323
480
None => Err ( FrameError :: Unknown ) ,
324
481
} ,
325
- Err ( e) if e. kind ( ) == ErrorKind :: UnexpectedEof => Err ( FrameError :: EOF ) ,
482
+ Err ( e) if e. kind ( ) == ErrorKind :: UnexpectedEof => Err ( FrameError :: Eof ) ,
326
483
// @TODO log e later
327
484
Err ( e) => Err ( FrameError :: IOError ) ,
328
485
}
@@ -360,7 +517,7 @@ where
360
517
) )
361
518
}
362
519
// The caller will treat EOF differently, so it needs to be returned explicitly
363
- Err ( e) if e. kind ( ) == ErrorKind :: UnexpectedEof => Err ( FrameError :: EOF ) ,
520
+ Err ( e) if e. kind ( ) == ErrorKind :: UnexpectedEof => Err ( FrameError :: Eof ) ,
364
521
// @TODO log e later
365
522
Err ( e) => Err ( FrameError :: IOError ) ,
366
523
}
@@ -369,6 +526,7 @@ where
369
526
#[ cfg( test) ]
370
527
mod tests {
371
528
use super :: * ;
529
+
372
530
#[ tokio:: test]
373
531
async fn decode_test ( ) {
374
532
//
@@ -394,7 +552,7 @@ mod tests {
394
552
let frame = decode ( & mut stream) . await ;
395
553
assert_eq ! (
396
554
frame,
397
- Err ( FrameError :: EOF ) ,
555
+ Err ( FrameError :: Eof ) ,
398
556
"should return EOF error variant"
399
557
) ;
400
558
@@ -441,7 +599,7 @@ mod tests {
441
599
let mut stream = BufReader :: new ( "*3\r \n :1\r \n +Two\r \n $5\r \n Three\r \n " . as_bytes ( ) ) ;
442
600
let frame = decode ( & mut stream) . await . unwrap ( ) ;
443
601
assert_eq ! ( frame. frame_type, FrameID :: Array ) ;
444
- let frame_data = Nested ( vec ! [
602
+ let frame_data = FrameData :: Nested ( vec ! [
445
603
Frame {
446
604
frame_type: FrameID :: Integer ,
447
605
frame_data: FrameData :: Integer ( 1 ) ,
@@ -461,7 +619,7 @@ mod tests {
461
619
let mut stream = BufReader :: new ( "*2\r \n :1\r \n *1\r \n +Three\r \n " . as_bytes ( ) ) ;
462
620
let frame = decode ( & mut stream) . await . unwrap ( ) ;
463
621
assert_eq ! ( frame. frame_type, FrameID :: Array ) ;
464
- let frame_data = Nested ( vec ! [
622
+ let frame_data = FrameData :: Nested ( vec ! [
465
623
Frame {
466
624
frame_type: FrameID :: Integer ,
467
625
frame_data: FrameData :: Integer ( 1 ) ,
@@ -480,7 +638,7 @@ mod tests {
480
638
let mut stream = BufReader :: new ( "*3\r \n :1\r \n *1\r \n +Three\r \n -Err\r \n " . as_bytes ( ) ) ;
481
639
let frame = decode ( & mut stream) . await . unwrap ( ) ;
482
640
assert_eq ! ( frame. frame_type, FrameID :: Array ) ;
483
- let frame_data = Nested ( vec ! [
641
+ let frame_data = FrameData :: Nested ( vec ! [
484
642
Frame {
485
643
frame_type: FrameID :: Integer ,
486
644
frame_data: FrameData :: Integer ( 1 ) ,
0 commit comments