@@ -23,15 +23,16 @@ pub(crate) struct Encoder {
2323 state : EncoderState ,
2424 /// Track bytes read in a call to poll_read.
2525 bytes_read : usize ,
26+ /// The data we're writing as part of the head section.
27+ head : Vec < u8 > ,
28+ /// The amount of bytes read from the head section.
29+ head_bytes_read : usize ,
2630}
2731
2832#[ derive( Debug ) ]
2933enum EncoderState {
3034 Start ,
31- Head {
32- data : Vec < u8 > ,
33- head_bytes_read : usize ,
34- } ,
35+ Head ,
3536 Body {
3637 body_bytes_read : usize ,
3738 body_len : usize ,
@@ -51,39 +52,79 @@ impl Encoder {
5152 res,
5253 state : EncoderState :: Start ,
5354 bytes_read : 0 ,
55+ head : vec ! [ ] ,
56+ head_bytes_read : 0 ,
5457 }
5558 }
59+ }
5660
57- fn encode_head ( & self ) -> io:: Result < Vec < u8 > > {
58- let mut head: Vec < u8 > = vec ! [ ] ;
61+ impl Encoder {
62+ // Encode the headers to a buffer, the first time we poll.
63+ fn encode_start ( & mut self ) -> io:: Result < ( ) > {
64+ self . state = EncoderState :: Head ;
5965
6066 let reason = self . res . status ( ) . canonical_reason ( ) ;
6167 let status = self . res . status ( ) ;
6268 std:: io:: Write :: write_fmt (
63- & mut head,
69+ & mut self . head ,
6470 format_args ! ( "HTTP/1.1 {} {}\r \n " , status, reason) ,
6571 ) ?;
6672
6773 // If the body isn't streaming, we can set the content-length ahead of time. Else we need to
6874 // send all items in chunks.
6975 if let Some ( len) = self . res . len ( ) {
70- std:: io:: Write :: write_fmt ( & mut head, format_args ! ( "content-length: {}\r \n " , len) ) ?;
76+ std:: io:: Write :: write_fmt ( & mut self . head , format_args ! ( "content-length: {}\r \n " , len) ) ?;
7177 } else {
72- std:: io:: Write :: write_fmt ( & mut head, format_args ! ( "transfer-encoding: chunked\r \n " ) ) ?;
78+ std:: io:: Write :: write_fmt (
79+ & mut self . head ,
80+ format_args ! ( "transfer-encoding: chunked\r \n " ) ,
81+ ) ?;
7382 }
7483
7584 let date = fmt_http_date ( std:: time:: SystemTime :: now ( ) ) ;
76- std:: io:: Write :: write_fmt ( & mut head, format_args ! ( "date: {}\r \n " , date) ) ?;
85+ std:: io:: Write :: write_fmt ( & mut self . head , format_args ! ( "date: {}\r \n " , date) ) ?;
7786
7887 for ( header, values) in self . res . iter ( ) {
7988 for value in values. iter ( ) {
80- std:: io:: Write :: write_fmt ( & mut head, format_args ! ( "{}: {}\r \n " , header, value) ) ?
89+ std:: io:: Write :: write_fmt (
90+ & mut self . head ,
91+ format_args ! ( "{}: {}\r \n " , header, value) ,
92+ ) ?
8193 }
8294 }
8395
84- std:: io:: Write :: write_fmt ( & mut head, format_args ! ( "\r \n " ) ) ?;
96+ std:: io:: Write :: write_fmt ( & mut self . head , format_args ! ( "\r \n " ) ) ?;
97+ Ok ( ( ) )
98+ }
8599
86- Ok ( head)
100+ /// Encode the status code + headers of the response.
101+ fn encode_head ( & mut self , buf : & mut [ u8 ] ) -> bool {
102+ // Read from the serialized headers, url and methods.
103+ let head_len = self . head . len ( ) ;
104+ let len = std:: cmp:: min ( head_len - self . head_bytes_read , buf. len ( ) ) ;
105+ let range = self . head_bytes_read ..self . head_bytes_read + len;
106+ buf[ 0 ..len] . copy_from_slice ( & self . head [ range] ) ;
107+ self . bytes_read += len;
108+ self . head_bytes_read += len;
109+
110+ // If we've read the total length of the head we're done
111+ // reading the head and can transition to reading the body
112+ if self . head_bytes_read == head_len {
113+ // The response length lets us know if we are encoding
114+ // our body in chunks or not
115+ self . state = match self . res . len ( ) {
116+ Some ( body_len) => EncoderState :: Body {
117+ body_bytes_read : 0 ,
118+ body_len,
119+ } ,
120+ None => EncoderState :: UncomputedChunked ,
121+ } ;
122+ true
123+ } else {
124+ // If we haven't read the entire header it means `buf` isn't
125+ // big enough. Break out of loop and return from `poll_read`
126+ false
127+ }
87128 }
88129}
89130
@@ -93,46 +134,14 @@ impl Read for Encoder {
93134 cx : & mut Context < ' _ > ,
94135 mut buf : & mut [ u8 ] ,
95136 ) -> Poll < io:: Result < usize > > {
96- // we must keep track how many bytes of the head and body we've read
137+ // we keep track how many bytes of the head and body we've read
97138 // in this call of `poll_read`
98139 self . bytes_read = 0 ;
99140 loop {
100141 match self . state {
101- EncoderState :: Start => {
102- // Encode the headers to a buffer, the first time we poll
103- let head = self . encode_head ( ) ?;
104- self . state = EncoderState :: Head {
105- data : head,
106- head_bytes_read : 0 ,
107- } ;
108- }
109- EncoderState :: Head {
110- ref data,
111- mut head_bytes_read,
112- } => {
113- // Read from the serialized headers, url and methods.
114- let head_len = data. len ( ) ;
115- let len = std:: cmp:: min ( head_len - head_bytes_read, buf. len ( ) ) ;
116- let range = head_bytes_read..head_bytes_read + len;
117- buf[ 0 ..len] . copy_from_slice ( & data[ range] ) ;
118- self . bytes_read += len;
119- head_bytes_read += len;
120-
121- // If we've read the total length of the head we're done
122- // reading the head and can transition to reading the body
123- if head_bytes_read == head_len {
124- // The response length lets us know if we are encoding
125- // our body in chunks or not
126- self . state = match self . res . len ( ) {
127- Some ( body_len) => EncoderState :: Body {
128- body_bytes_read : 0 ,
129- body_len,
130- } ,
131- None => EncoderState :: UncomputedChunked ,
132- } ;
133- } else {
134- // If we haven't read the entire header it means `buf` isn't
135- // big enough. Break out of loop and return from `poll_read`
142+ EncoderState :: Start => self . encode_start ( ) ?,
143+ EncoderState :: Head { .. } => {
144+ if !self . encode_head ( buf) {
136145 break ;
137146 }
138147 }
0 commit comments