@@ -31,9 +31,9 @@ const MAX_BUF_LIST_BUFFERS: usize = 16;
31
31
pub struct Buffered < T , B > {
32
32
flush_pipeline : bool ,
33
33
io : T ,
34
- max_buf_size : usize ,
35
34
read_blocked : bool ,
36
35
read_buf : BytesMut ,
36
+ read_buf_strategy : ReadStrategy ,
37
37
write_buf : WriteBuf < B > ,
38
38
}
39
39
@@ -58,10 +58,12 @@ where
58
58
Buffered {
59
59
flush_pipeline : false ,
60
60
io : io,
61
- max_buf_size : DEFAULT_MAX_BUFFER_SIZE ,
61
+ read_blocked : false ,
62
62
read_buf : BytesMut :: with_capacity ( 0 ) ,
63
+ read_buf_strategy : ReadStrategy :: Adaptive {
64
+ max : DEFAULT_MAX_BUFFER_SIZE ,
65
+ } ,
63
66
write_buf : WriteBuf :: new ( ) ,
64
- read_blocked : false ,
65
67
}
66
68
}
67
69
@@ -76,17 +78,24 @@ where
76
78
pub fn set_max_buf_size ( & mut self , max : usize ) {
77
79
assert ! (
78
80
max >= MINIMUM_MAX_BUFFER_SIZE ,
79
- "The max_buf_size cannot be smaller than the initial buffer size."
81
+ "The max_buf_size cannot be smaller than {}." ,
82
+ MINIMUM_MAX_BUFFER_SIZE ,
80
83
) ;
81
- self . max_buf_size = max;
84
+ self . read_buf_strategy = ReadStrategy :: Adaptive {
85
+ max,
86
+ } ;
82
87
self . write_buf . max_buf_size = max;
83
88
}
84
89
90
+ pub fn set_read_buf_exact_size ( & mut self , sz : usize ) {
91
+ self . read_buf_strategy = ReadStrategy :: Exact ( sz) ;
92
+ }
93
+
85
94
pub fn set_write_strategy_flatten ( & mut self ) {
86
95
// this should always be called only at construction time,
87
96
// so this assert is here to catch myself
88
97
debug_assert ! ( self . write_buf. queue. bufs. is_empty( ) ) ;
89
- self . write_buf . set_strategy ( Strategy :: Flatten ) ;
98
+ self . write_buf . set_strategy ( WriteStrategy :: Flatten ) ;
90
99
}
91
100
92
101
pub fn read_buf ( & self ) -> & [ u8 ] {
@@ -140,10 +149,18 @@ where
140
149
debug ! ( "parsed {} headers" , msg. head. headers. len( ) ) ;
141
150
return Ok ( Async :: Ready ( msg) )
142
151
} ,
143
- None => {
144
- if self . read_buf . capacity ( ) >= self . max_buf_size {
145
- debug ! ( "max_buf_size ({}) reached, closing" , self . max_buf_size) ;
146
- return Err ( :: Error :: new_too_large ( ) ) ;
152
+ None => match self . read_buf_strategy {
153
+ ReadStrategy :: Adaptive { max } => {
154
+ if self . read_buf . len ( ) >= max {
155
+ debug ! ( "max_buf_size ({}) reached, closing" , max) ;
156
+ return Err ( :: Error :: new_too_large ( ) ) ;
157
+ }
158
+ } ,
159
+ ReadStrategy :: Exact ( exact) => {
160
+ if self . read_buf . len ( ) >= exact {
161
+ debug ! ( "exact buf size ({}) filled, closing" , exact) ;
162
+ return Err ( :: Error :: new_too_large ( ) ) ;
163
+ }
147
164
}
148
165
} ,
149
166
}
@@ -160,8 +177,17 @@ where
160
177
pub fn read_from_io ( & mut self ) -> Poll < usize , io:: Error > {
161
178
use bytes:: BufMut ;
162
179
self . read_blocked = false ;
163
- if self . read_buf . remaining_mut ( ) < INIT_BUFFER_SIZE {
164
- self . read_buf . reserve ( INIT_BUFFER_SIZE ) ;
180
+ match self . read_buf_strategy {
181
+ ReadStrategy :: Adaptive { .. } => {
182
+ if self . read_buf . remaining_mut ( ) < INIT_BUFFER_SIZE {
183
+ self . read_buf . reserve ( INIT_BUFFER_SIZE ) ;
184
+ }
185
+ } ,
186
+ ReadStrategy :: Exact ( exact) => {
187
+ if self . read_buf . capacity ( ) < exact {
188
+ self . read_buf . reserve ( exact) ;
189
+ }
190
+ } ,
165
191
}
166
192
self . io . read_buf ( & mut self . read_buf ) . map ( |ok| {
167
193
match ok {
@@ -196,7 +222,7 @@ where
196
222
try_nb ! ( self . io. flush( ) ) ;
197
223
} else {
198
224
match self . write_buf . strategy {
199
- Strategy :: Flatten => return self . flush_flattened ( ) ,
225
+ WriteStrategy :: Flatten => return self . flush_flattened ( ) ,
200
226
_ => ( ) ,
201
227
}
202
228
loop {
@@ -256,6 +282,14 @@ where
256
282
}
257
283
}
258
284
285
+ #[ derive( Clone , Copy , Debug ) ]
286
+ enum ReadStrategy {
287
+ Adaptive {
288
+ max : usize
289
+ } ,
290
+ Exact ( usize ) ,
291
+ }
292
+
259
293
#[ derive( Clone ) ]
260
294
pub struct Cursor < T > {
261
295
bytes : T ,
@@ -313,7 +347,7 @@ pub(super) struct WriteBuf<B> {
313
347
max_buf_size : usize ,
314
348
/// Deque of user buffers if strategy is Queue
315
349
queue : BufDeque < B > ,
316
- strategy : Strategy ,
350
+ strategy : WriteStrategy ,
317
351
}
318
352
319
353
impl < B > WriteBuf < B > {
@@ -322,7 +356,7 @@ impl<B> WriteBuf<B> {
322
356
headers : Cursor :: new ( Vec :: with_capacity ( INIT_BUFFER_SIZE ) ) ,
323
357
max_buf_size : DEFAULT_MAX_BUFFER_SIZE ,
324
358
queue : BufDeque :: new ( ) ,
325
- strategy : Strategy :: Auto ,
359
+ strategy : WriteStrategy :: Auto ,
326
360
}
327
361
}
328
362
}
@@ -332,7 +366,7 @@ impl<B> WriteBuf<B>
332
366
where
333
367
B : Buf ,
334
368
{
335
- fn set_strategy ( & mut self , strategy : Strategy ) {
369
+ fn set_strategy ( & mut self , strategy : WriteStrategy ) {
336
370
self . strategy = strategy;
337
371
}
338
372
@@ -344,7 +378,7 @@ where
344
378
pub ( super ) fn buffer < BB : Buf + Into < B > > ( & mut self , mut buf : BB ) {
345
379
debug_assert ! ( buf. has_remaining( ) ) ;
346
380
match self . strategy {
347
- Strategy :: Flatten => {
381
+ WriteStrategy :: Flatten => {
348
382
let head = self . headers_mut ( ) ;
349
383
//perf: This is a little faster than <Vec as BufMut>>::put,
350
384
//but accomplishes the same result.
@@ -360,18 +394,18 @@ where
360
394
buf. advance ( adv) ;
361
395
}
362
396
} ,
363
- Strategy :: Auto | Strategy :: Queue => {
397
+ WriteStrategy :: Auto | WriteStrategy :: Queue => {
364
398
self . queue . bufs . push_back ( buf. into ( ) ) ;
365
399
} ,
366
400
}
367
401
}
368
402
369
403
fn can_buffer ( & self ) -> bool {
370
404
match self . strategy {
371
- Strategy :: Flatten => {
405
+ WriteStrategy :: Flatten => {
372
406
self . remaining ( ) < self . max_buf_size
373
407
} ,
374
- Strategy :: Auto | Strategy :: Queue => {
408
+ WriteStrategy :: Auto | WriteStrategy :: Queue => {
375
409
self . queue . bufs . len ( ) < MAX_BUF_LIST_BUFFERS
376
410
&& self . remaining ( ) < self . max_buf_size
377
411
} ,
@@ -474,12 +508,12 @@ impl<'a, B: Buf> Buf for WriteBufAuto<'a, B> {
474
508
475
509
impl < ' a , B : Buf + ' a > Drop for WriteBufAuto < ' a , B > {
476
510
fn drop ( & mut self ) {
477
- if let Strategy :: Auto = self . inner . strategy {
511
+ if let WriteStrategy :: Auto = self . inner . strategy {
478
512
if self . bytes_vec_called . get ( ) {
479
- self . inner . strategy = Strategy :: Queue ;
513
+ self . inner . strategy = WriteStrategy :: Queue ;
480
514
} else if self . bytes_called . get ( ) {
481
515
trace ! ( "detected no usage of vectored write, flattening" ) ;
482
- self . inner . strategy = Strategy :: Flatten ;
516
+ self . inner . strategy = WriteStrategy :: Flatten ;
483
517
self . inner . headers . bytes . put ( & mut self . inner . queue ) ;
484
518
}
485
519
}
@@ -488,7 +522,7 @@ impl<'a, B: Buf + 'a> Drop for WriteBufAuto<'a, B> {
488
522
489
523
490
524
#[ derive( Debug ) ]
491
- enum Strategy {
525
+ enum WriteStrategy {
492
526
Auto ,
493
527
Flatten ,
494
528
Queue ,
@@ -640,7 +674,7 @@ mod tests {
640
674
641
675
let mock = AsyncIo :: new_buf ( vec ! [ ] , 1024 ) ;
642
676
let mut buffered = Buffered :: < _ , Cursor < Vec < u8 > > > :: new ( mock) ;
643
- buffered. write_buf . set_strategy ( Strategy :: Flatten ) ;
677
+ buffered. write_buf . set_strategy ( WriteStrategy :: Flatten ) ;
644
678
645
679
buffered. headers_buf ( ) . extend ( b"hello " ) ;
646
680
buffered. buffer ( Cursor :: new ( b"world, " . to_vec ( ) ) ) ;
@@ -686,7 +720,7 @@ mod tests {
686
720
let mut mock = AsyncIo :: new_buf ( vec ! [ ] , 1024 ) ;
687
721
mock. max_read_vecs ( 0 ) ; // disable vectored IO
688
722
let mut buffered = Buffered :: < _ , Cursor < Vec < u8 > > > :: new ( mock) ;
689
- buffered. write_buf . set_strategy ( Strategy :: Queue ) ;
723
+ buffered. write_buf . set_strategy ( WriteStrategy :: Queue ) ;
690
724
691
725
// we have 4 buffers, and vec IO disabled, but explicitly said
692
726
// don't try to auto detect (via setting strategy above)
@@ -710,7 +744,7 @@ mod tests {
710
744
b. bytes = s. len ( ) as u64 ;
711
745
712
746
let mut write_buf = WriteBuf :: < :: Chunk > :: new ( ) ;
713
- write_buf. set_strategy ( Strategy :: Flatten ) ;
747
+ write_buf. set_strategy ( WriteStrategy :: Flatten ) ;
714
748
b. iter ( || {
715
749
let chunk = :: Chunk :: from ( s) ;
716
750
write_buf. buffer ( chunk) ;
0 commit comments