1
1
use std:: fmt;
2
2
use std:: future:: Future ;
3
+ use std:: ops:: Range ;
3
4
use std:: pin:: Pin ;
4
5
use std:: str:: FromStr ;
5
6
use std:: task:: { Context , Poll } ;
@@ -24,8 +25,8 @@ pub(crate) struct ChunkedDecoder<R: Read> {
24
25
inner : R ,
25
26
/// Buffer for the already read, but not yet parsed data.
26
27
buffer : Block < ' static > ,
27
- /// Position of valid read data into buffer.
28
- current : Position ,
28
+ /// Range of valid read data into buffer.
29
+ current : Range < usize > ,
29
30
/// Whether we should attempt to decode whatever is currently inside the buffer.
30
31
/// False indicates that we know for certain that the buffer is incomplete.
31
32
initial_decode : bool ,
@@ -44,7 +45,7 @@ impl<R: Read> ChunkedDecoder<R> {
44
45
ChunkedDecoder {
45
46
inner,
46
47
buffer : POOL . alloc ( INITIAL_CAPACITY ) ,
47
- current : Position :: default ( ) ,
48
+ current : Range { start : 0 , end : 0 } ,
48
49
initial_decode : false , // buffer is empty initially, nothing to decode}
49
50
state : State :: Init ,
50
51
trailer_sender : sender,
@@ -62,7 +63,7 @@ impl<R: Read + Unpin> ChunkedDecoder<R> {
62
63
& mut self ,
63
64
cx : & mut Context < ' _ > ,
64
65
buffer : Block < ' static > ,
65
- pos : & Position ,
66
+ pos : & Range < usize > ,
66
67
buf : & mut [ u8 ] ,
67
68
current : u64 ,
68
69
len : u64 ,
@@ -100,6 +101,7 @@ impl<R: Read + Unpin> ChunkedDecoder<R> {
100
101
} ) ;
101
102
}
102
103
104
+ // attempt to fill the buffer
103
105
match Pin :: new ( & mut self . inner ) . poll_read ( cx, & mut buf[ read..read + to_read] ) {
104
106
Poll :: Ready ( val) => {
105
107
let n = val?;
@@ -135,7 +137,7 @@ impl<R: Read + Unpin> ChunkedDecoder<R> {
135
137
& mut self ,
136
138
cx : & mut Context < ' _ > ,
137
139
buffer : Block < ' static > ,
138
- pos : & Position ,
140
+ pos : & Range < usize > ,
139
141
buf : & mut [ u8 ] ,
140
142
) -> io:: Result < DecodeResult > {
141
143
match self . state {
@@ -196,7 +198,7 @@ impl<R: Read + Unpin> Read for ChunkedDecoder<R> {
196
198
) -> Poll < io:: Result < usize > > {
197
199
let this = & mut * self ;
198
200
199
- let mut n = std:: mem:: replace ( & mut this. current , Position :: default ( ) ) ;
201
+ let mut n = std:: mem:: replace ( & mut this. current , 0 .. 0 ) ;
200
202
let buffer = std:: mem:: replace ( & mut this. buffer , POOL . alloc ( INITIAL_CAPACITY ) ) ;
201
203
let mut needs_read = if let State :: Chunk ( _, _) = this. state {
202
204
false // Do not attempt to fill the buffer when we are reading a chunk
@@ -205,6 +207,7 @@ impl<R: Read + Unpin> Read for ChunkedDecoder<R> {
205
207
} ;
206
208
207
209
let mut buffer = if n. len ( ) > 0 && this. initial_decode {
210
+ // initial buffer filling, if needed
208
211
match this. poll_read_inner ( cx, buffer, & n, buf) ? {
209
212
DecodeResult :: Some {
210
213
read,
@@ -279,7 +282,7 @@ impl<R: Read + Unpin> Read for ChunkedDecoder<R> {
279
282
// to decode it next time
280
283
this. initial_decode = true ;
281
284
this. state = new_state;
282
- this. current = new_pos;
285
+ this. current = new_pos. clone ( ) ;
283
286
n = new_pos;
284
287
285
288
if State :: Done == this. state || read > 0 {
@@ -299,7 +302,7 @@ impl<R: Read + Unpin> Read for ChunkedDecoder<R> {
299
302
DecodeResult :: None ( buf) => {
300
303
buffer = buf;
301
304
302
- if this. buffer . is_empty ( ) || n. is_zero ( ) {
305
+ if this. buffer . is_empty ( ) || n. start == 0 && n . end == 0 {
303
306
// "logical buffer" is empty, there is nothing to decode on the next step
304
307
this. initial_decode = false ;
305
308
this. buffer = buffer;
@@ -315,43 +318,39 @@ impl<R: Read + Unpin> Read for ChunkedDecoder<R> {
315
318
}
316
319
}
317
320
318
- /// A semantically explicit slice of a buffer.
319
- #[ derive( Eq , PartialEq , Debug , Copy , Clone , Default ) ]
320
- struct Position {
321
- start : usize ,
322
- end : usize ,
323
- }
324
-
325
- impl Position {
326
- fn len ( & self ) -> usize {
327
- self . end - self . start
328
- }
329
-
330
- fn is_zero ( & self ) -> bool {
331
- self . start == 0 && self . end == 0
332
- }
333
- }
334
-
321
+ /// Possible return values from calling `decode` methods.
335
322
enum DecodeResult {
323
+ /// Something was decoded successfully.
336
324
Some {
337
- /// How much was read
325
+ /// How much data was read.
338
326
read : usize ,
339
- /// Remaining data .
327
+ /// The passed in block returned .
340
328
buffer : Block < ' static > ,
341
- new_pos : Position ,
329
+ /// The new range of valid data in `buffer`.
330
+ new_pos : Range < usize > ,
331
+ /// The new state.
342
332
new_state : State ,
333
+ /// Should poll return `Pending`.
343
334
pending : bool ,
344
335
} ,
336
+ /// Nothing was decoded.
345
337
None ( Block < ' static > ) ,
346
338
}
347
339
340
+ /// Decoder state.
348
341
#[ derive( Debug , PartialEq , Clone ) ]
349
342
enum State {
343
+ /// Initial state.
350
344
Init ,
345
+ /// Decoding a chunk, first value is the current position, second value is the length of the chunk.
351
346
Chunk ( u64 , u64 ) ,
347
+ /// Decoding the end part of a chunk.
352
348
ChunkEnd ,
349
+ /// Decoding trailers.
353
350
Trailer ,
351
+ /// Trailers were decoded, are now set to the decoded trailers.
354
352
TrailerDone ( Vec < ( HeaderName , HeaderValue ) > ) ,
353
+ /// All is said and done.
355
354
Done ,
356
355
}
357
356
@@ -377,11 +376,11 @@ impl fmt::Debug for DecodeResult {
377
376
}
378
377
}
379
378
380
- fn decode_init ( buffer : Block < ' static > , pos : & Position ) -> io:: Result < DecodeResult > {
379
+ fn decode_init ( buffer : Block < ' static > , pos : & Range < usize > ) -> io:: Result < DecodeResult > {
381
380
use httparse:: Status ;
382
381
match httparse:: parse_chunk_size ( & buffer[ pos. start ..pos. end ] ) {
383
382
Ok ( Status :: Complete ( ( used, chunk_len) ) ) => {
384
- let new_pos = Position {
383
+ let new_pos = Range {
385
384
start : pos. start + used,
386
385
end : pos. end ,
387
386
} ;
@@ -405,7 +404,7 @@ fn decode_init(buffer: Block<'static>, pos: &Position) -> io::Result<DecodeResul
405
404
}
406
405
}
407
406
408
- fn decode_chunk_end ( buffer : Block < ' static > , pos : & Position ) -> io:: Result < DecodeResult > {
407
+ fn decode_chunk_end ( buffer : Block < ' static > , pos : & Range < usize > ) -> io:: Result < DecodeResult > {
409
408
if pos. len ( ) < 2 {
410
409
return Ok ( DecodeResult :: None ( buffer) ) ;
411
410
}
@@ -415,7 +414,7 @@ fn decode_chunk_end(buffer: Block<'static>, pos: &Position) -> io::Result<Decode
415
414
return Ok ( DecodeResult :: Some {
416
415
read : 0 ,
417
416
buffer,
418
- new_pos : Position {
417
+ new_pos : Range {
419
418
start : pos. start + 2 ,
420
419
end : pos. end ,
421
420
} ,
@@ -427,7 +426,7 @@ fn decode_chunk_end(buffer: Block<'static>, pos: &Position) -> io::Result<Decode
427
426
Err ( io:: Error :: from ( io:: ErrorKind :: InvalidData ) )
428
427
}
429
428
430
- fn decode_trailer ( buffer : Block < ' static > , pos : & Position ) -> io:: Result < DecodeResult > {
429
+ fn decode_trailer ( buffer : Block < ' static > , pos : & Range < usize > ) -> io:: Result < DecodeResult > {
431
430
use httparse:: Status ;
432
431
433
432
// read headers
@@ -450,7 +449,7 @@ fn decode_trailer(buffer: Block<'static>, pos: &Position) -> io::Result<DecodeRe
450
449
read : 0 ,
451
450
buffer,
452
451
new_state : State :: TrailerDone ( headers) ,
453
- new_pos : Position {
452
+ new_pos : Range {
454
453
start : pos. start + used,
455
454
end : pos. end ,
456
455
} ,
0 commit comments