1
+ use std:: fmt;
1
2
use std:: usize;
2
3
use std:: io;
3
4
@@ -11,33 +12,21 @@ use self::Kind::{Length, Chunked, Eof};
11
12
///
12
13
/// If a message body does not include a Transfer-Encoding, it *should*
13
14
/// include a Content-Length header.
14
- #[ derive( Debug , Clone , PartialEq ) ]
15
+ #[ derive( Clone , PartialEq ) ]
15
16
pub struct Decoder {
16
17
kind : Kind ,
17
18
}
18
19
19
- impl Decoder {
20
- pub fn length ( x : u64 ) -> Decoder {
21
- Decoder { kind : Kind :: Length ( x) }
22
- }
23
-
24
- pub fn chunked ( ) -> Decoder {
25
- Decoder { kind : Kind :: Chunked ( ChunkedState :: Size , 0 ) }
26
- }
27
-
28
- pub fn eof ( ) -> Decoder {
29
- Decoder { kind : Kind :: Eof ( false ) }
30
- }
31
- }
32
-
33
- #[ derive( Debug , Clone , PartialEq ) ]
20
+ #[ derive( Debug , Clone , Copy , PartialEq ) ]
34
21
enum Kind {
35
22
/// A Reader used when a Content-Length header is passed with a positive integer.
36
23
Length ( u64 ) ,
37
24
/// A Reader used when Transfer-Encoding is `chunked`.
38
25
Chunked ( ChunkedState , u64 ) ,
39
26
/// A Reader used for responses that don't indicate a length or chunked.
40
27
///
28
+ /// The bool tracks when EOF is seen on the transport.
29
+ ///
41
30
/// Note: This should only used for `Response`s. It is illegal for a
42
31
/// `Request` to be made with both `Content-Length` and
43
32
/// `Transfer-Encoding: chunked` missing, as explained from the spec:
@@ -53,7 +42,7 @@ enum Kind {
53
42
Eof ( bool ) ,
54
43
}
55
44
56
- #[ derive( Debug , PartialEq , Clone ) ]
45
+ #[ derive( Debug , PartialEq , Clone , Copy ) ]
57
46
enum ChunkedState {
58
47
Size ,
59
48
SizeLws ,
@@ -68,6 +57,22 @@ enum ChunkedState {
68
57
}
69
58
70
59
impl Decoder {
60
+ // constructors
61
+
62
+ pub fn length ( x : u64 ) -> Decoder {
63
+ Decoder { kind : Kind :: Length ( x) }
64
+ }
65
+
66
+ pub fn chunked ( ) -> Decoder {
67
+ Decoder { kind : Kind :: Chunked ( ChunkedState :: Size , 0 ) }
68
+ }
69
+
70
+ pub fn eof ( ) -> Decoder {
71
+ Decoder { kind : Kind :: Eof ( false ) }
72
+ }
73
+
74
+ // methods
75
+
71
76
pub fn is_eof ( & self ) -> bool {
72
77
trace ! ( "is_eof? {:?}" , self ) ;
73
78
match self . kind {
@@ -77,9 +82,7 @@ impl Decoder {
77
82
_ => false ,
78
83
}
79
84
}
80
- }
81
85
82
- impl Decoder {
83
86
pub fn decode < R : MemRead > ( & mut self , body : & mut R ) -> Poll < Bytes , io:: Error > {
84
87
match self . kind {
85
88
Length ( ref mut remaining) => {
@@ -131,6 +134,23 @@ impl Decoder {
131
134
}
132
135
}
133
136
137
+
138
+ impl fmt:: Debug for Decoder {
139
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
140
+ fmt:: Debug :: fmt ( & self . kind , f)
141
+ }
142
+ }
143
+
144
+ impl fmt:: Display for Decoder {
145
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
146
+ match self . kind {
147
+ Kind :: Length ( n) => write ! ( f, "content-length ({} bytes)" , n) ,
148
+ Kind :: Chunked ( ..) => f. write_str ( "chunked encoded" ) ,
149
+ Kind :: Eof ( ..) => f. write_str ( "until end-of-file" ) ,
150
+ }
151
+ }
152
+ }
153
+
134
154
macro_rules! byte (
135
155
( $rdr: ident) => ( {
136
156
let buf = try_ready!( $rdr. read_mem( 1 ) ) ;
@@ -154,7 +174,7 @@ impl ChunkedState {
154
174
Size => ChunkedState :: read_size ( body, size) ,
155
175
SizeLws => ChunkedState :: read_size_lws ( body) ,
156
176
Extension => ChunkedState :: read_extension ( body) ,
157
- SizeLf => ChunkedState :: read_size_lf ( body, size) ,
177
+ SizeLf => ChunkedState :: read_size_lf ( body, * size) ,
158
178
Body => ChunkedState :: read_body ( body, size, buf) ,
159
179
BodyCr => ChunkedState :: read_body_cr ( body) ,
160
180
BodyLf => ChunkedState :: read_body_lf ( body) ,
@@ -209,11 +229,17 @@ impl ChunkedState {
209
229
_ => Ok ( Async :: Ready ( ChunkedState :: Extension ) ) , // no supported extensions
210
230
}
211
231
}
212
- fn read_size_lf < R : MemRead > ( rdr : & mut R , size : & mut u64 ) -> Poll < ChunkedState , io:: Error > {
232
+ fn read_size_lf < R : MemRead > ( rdr : & mut R , size : u64 ) -> Poll < ChunkedState , io:: Error > {
213
233
trace ! ( "Chunk size is {:?}" , size) ;
214
234
match byte ! ( rdr) {
215
- b'\n' if * size > 0 => Ok ( Async :: Ready ( ChunkedState :: Body ) ) ,
216
- b'\n' if * size == 0 => Ok ( Async :: Ready ( ChunkedState :: EndCr ) ) ,
235
+ b'\n' => {
236
+ if size == 0 {
237
+ Ok ( Async :: Ready ( ChunkedState :: EndCr ) )
238
+ } else {
239
+ debug ! ( "incoming chunked header: {0:#X} ({0} bytes)" , size) ;
240
+ Ok ( Async :: Ready ( ChunkedState :: Body ) )
241
+ }
242
+ } ,
217
243
_ => Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput , "Invalid chunk size LF" ) ) ,
218
244
}
219
245
}
0 commit comments