1+ use std:: fmt;
12use std:: usize;
23use std:: io;
34
@@ -11,33 +12,21 @@ use self::Kind::{Length, Chunked, Eof};
1112///
1213/// If a message body does not include a Transfer-Encoding, it *should*
1314/// include a Content-Length header.
14- #[ derive( Debug , Clone , PartialEq ) ]
15+ #[ derive( Clone , PartialEq ) ]
1516pub struct Decoder {
1617 kind : Kind ,
1718}
1819
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 ) ]
3421enum Kind {
3522 /// A Reader used when a Content-Length header is passed with a positive integer.
3623 Length ( u64 ) ,
3724 /// A Reader used when Transfer-Encoding is `chunked`.
3825 Chunked ( ChunkedState , u64 ) ,
3926 /// A Reader used for responses that don't indicate a length or chunked.
4027 ///
28+ /// The bool tracks when EOF is seen on the transport.
29+ ///
4130 /// Note: This should only used for `Response`s. It is illegal for a
4231 /// `Request` to be made with both `Content-Length` and
4332 /// `Transfer-Encoding: chunked` missing, as explained from the spec:
@@ -53,7 +42,7 @@ enum Kind {
5342 Eof ( bool ) ,
5443}
5544
56- #[ derive( Debug , PartialEq , Clone ) ]
45+ #[ derive( Debug , PartialEq , Clone , Copy ) ]
5746enum ChunkedState {
5847 Size ,
5948 SizeLws ,
@@ -68,6 +57,22 @@ enum ChunkedState {
6857}
6958
7059impl 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+
7176 pub fn is_eof ( & self ) -> bool {
7277 trace ! ( "is_eof? {:?}" , self ) ;
7378 match self . kind {
@@ -77,9 +82,7 @@ impl Decoder {
7782 _ => false ,
7883 }
7984 }
80- }
8185
82- impl Decoder {
8386 pub fn decode < R : MemRead > ( & mut self , body : & mut R ) -> Poll < Bytes , io:: Error > {
8487 match self . kind {
8588 Length ( ref mut remaining) => {
@@ -131,6 +134,23 @@ impl Decoder {
131134 }
132135}
133136
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+
134154macro_rules! byte (
135155 ( $rdr: ident) => ( {
136156 let buf = try_ready!( $rdr. read_mem( 1 ) ) ;
@@ -154,7 +174,7 @@ impl ChunkedState {
154174 Size => ChunkedState :: read_size ( body, size) ,
155175 SizeLws => ChunkedState :: read_size_lws ( body) ,
156176 Extension => ChunkedState :: read_extension ( body) ,
157- SizeLf => ChunkedState :: read_size_lf ( body, size) ,
177+ SizeLf => ChunkedState :: read_size_lf ( body, * size) ,
158178 Body => ChunkedState :: read_body ( body, size, buf) ,
159179 BodyCr => ChunkedState :: read_body_cr ( body) ,
160180 BodyLf => ChunkedState :: read_body_lf ( body) ,
@@ -209,11 +229,17 @@ impl ChunkedState {
209229 _ => Ok ( Async :: Ready ( ChunkedState :: Extension ) ) , // no supported extensions
210230 }
211231 }
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 > {
213233 trace ! ( "Chunk size is {:?}" , size) ;
214234 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+ } ,
217243 _ => Err ( io:: Error :: new ( io:: ErrorKind :: InvalidInput , "Invalid chunk size LF" ) ) ,
218244 }
219245 }
0 commit comments