@@ -101,7 +101,11 @@ enum EncoderState {
101
101
body_bytes_read : usize ,
102
102
body_len : usize ,
103
103
} ,
104
- Chunked ,
104
+ UncomputedChunked ,
105
+ ComputedChunked {
106
+ chunk : io:: Cursor < Vec < u8 > > ,
107
+ is_last : bool ,
108
+ } ,
105
109
Done ,
106
110
}
107
111
@@ -149,13 +153,12 @@ impl Read for Encoder {
149
153
fn poll_read (
150
154
mut self : Pin < & mut Self > ,
151
155
cx : & mut Context < ' _ > ,
152
- buf : & mut [ u8 ] ,
156
+ mut buf : & mut [ u8 ] ,
153
157
) -> Poll < io:: Result < usize > > {
154
158
// we must keep track how many bytes of the head and body we've read
155
159
// in this call of `poll_read`
156
160
let mut bytes_read = 0 ;
157
161
loop {
158
- println ! ( "{:?}" , self . state) ;
159
162
match self . state {
160
163
EncoderState :: Start => {
161
164
// Encode the headers to a buffer, the first time we poll
@@ -181,14 +184,18 @@ impl Read for Encoder {
181
184
// reading the head and can transition to reading the body
182
185
if head_bytes_read == head_len {
183
186
// The response length lets us know if we are encoding
184
- // our body in chunks or now
187
+ // our body in chunks or not
185
188
self . state = match self . res . len ( ) {
186
189
Some ( body_len) => EncoderState :: Body {
187
190
body_bytes_read : 0 ,
188
191
body_len,
189
192
} ,
190
- None => EncoderState :: Chunked ,
193
+ None => EncoderState :: UncomputedChunked ,
191
194
} ;
195
+ } else {
196
+ // If we haven't read the entire header it means `buf` isn't
197
+ // big enough. Break out of loop and return from `poll_read`
198
+ break ;
192
199
}
193
200
}
194
201
EncoderState :: Body {
@@ -203,9 +210,10 @@ impl Read for Encoder {
203
210
if bytes_read == buf. len ( ) {
204
211
break ;
205
212
}
206
- // figure out how many bytes we can read
213
+
214
+ // Figure out how many bytes we can read.
207
215
let upper_bound = ( bytes_read + body_len - body_bytes_read) . min ( buf. len ( ) ) ;
208
- // Read bytes, and update internal tracking stuff.
216
+ // Read bytes from body
209
217
let new_body_bytes_read =
210
218
ready ! ( Pin :: new( & mut self . res)
211
219
. poll_read( cx, & mut buf[ bytes_read..upper_bound] ) ) ?;
@@ -220,8 +228,8 @@ impl Read for Encoder {
220
228
body_len,
221
229
body_bytes_read
222
230
) ;
223
- // If we've read the `len` number of bytes or the stream no longer gives bytes , end.
224
- self . state = if body_len == body_bytes_read || body_bytes_read == 0 {
231
+ // If we've read the `len` number of bytes, end
232
+ self . state = if body_len == body_bytes_read {
225
233
EncoderState :: Done
226
234
} else {
227
235
EncoderState :: Body {
@@ -230,15 +238,15 @@ impl Read for Encoder {
230
238
}
231
239
} ;
232
240
}
233
- EncoderState :: Chunked => {
234
- // ensure we have at least room for 1 more byte in our buffer
235
- if bytes_read == buf. len ( ) {
236
- break ;
237
- }
238
-
241
+ EncoderState :: UncomputedChunked => {
239
242
// We can read a maximum of the buffer's total size
240
243
// minus what we've already filled the buffer with
241
244
let buffer_remaining = buf. len ( ) - bytes_read;
245
+
246
+ // ensure we have at least room for 1 byte in our buffer
247
+ if buffer_remaining == 0 {
248
+ break ;
249
+ }
242
250
// we must allocate a separate buffer for the chunk data
243
251
// since we first need to know its length before writing
244
252
// it into the actual buffer
@@ -282,22 +290,53 @@ impl Read for Encoder {
282
290
buf[ bytes_read] = b'\r' ;
283
291
buf[ bytes_read + 1 ] = b'\n' ;
284
292
bytes_read += 2 ;
293
+
294
+ if chunk_length == 0 {
295
+ self . state = EncoderState :: Done ;
296
+ }
285
297
} else {
286
- unimplemented ! ( "TODO: handle when buf isn't big enough" ) ;
287
- }
288
- const EMPTY_CHUNK : & [ u8 ; 5 ] = b"0\r \n \r \n " ;
298
+ let mut chunk = vec ! [ 0 ; total_chunk_size] ;
299
+ let mut bytes_written = 0 ;
300
+ // Write the chunk length into the buffer
301
+ chunk[ 0 ..chunk_length_bytes_len] . copy_from_slice ( chunk_length_bytes) ;
302
+ bytes_written += chunk_length_bytes_len;
289
303
290
- buf[ bytes_read..bytes_read + EMPTY_CHUNK . len ( ) ] . copy_from_slice ( EMPTY_CHUNK ) ;
304
+ // follow chunk length with CRLF
305
+ chunk[ bytes_written] = b'\r' ;
306
+ chunk[ bytes_written + 1 ] = b'\n' ;
307
+ bytes_written += 2 ;
291
308
292
- // if body_bytes_read == 0 {
293
- bytes_read += 7 ;
294
- self . state = EncoderState :: Done ;
295
- // }
309
+ // copy chunk into buf
310
+ chunk[ bytes_written..bytes_written + chunk_length]
311
+ . copy_from_slice ( & chunk_buf[ ..chunk_length] ) ;
312
+ bytes_written += chunk_length;
313
+
314
+ // follow chunk with CRLF
315
+ chunk[ bytes_written] = b'\r' ;
316
+ chunk[ bytes_written + 1 ] = b'\n' ;
317
+ bytes_read += 2 ;
318
+ self . state = EncoderState :: ComputedChunked {
319
+ chunk : io:: Cursor :: new ( chunk) ,
320
+ is_last : chunk_length == 0 ,
321
+ } ;
322
+ }
323
+ }
324
+ EncoderState :: ComputedChunked {
325
+ ref mut chunk,
326
+ is_last,
327
+ } => {
328
+ bytes_read += ready ! ( Pin :: new( chunk) . poll_read( cx, & mut buf) ) ?;
329
+ if bytes_read == 0 {
330
+ self . state = match is_last {
331
+ true => EncoderState :: Done ,
332
+ false => EncoderState :: UncomputedChunked ,
333
+ }
334
+ }
335
+ break ;
296
336
}
297
337
EncoderState :: Done => break ,
298
338
}
299
339
}
300
- println ! ( "{:?}" , std:: str :: from_utf8( & buf[ 0 ..bytes_read] ) ) ;
301
340
302
341
Poll :: Ready ( Ok ( bytes_read as usize ) )
303
342
}
0 commit comments