@@ -5,6 +5,7 @@ use std::cmp;
55use std:: future:: Future ;
66use std:: io;
77use std:: io:: prelude:: * ;
8+ use std:: mem:: MaybeUninit ;
89use std:: pin:: Pin ;
910use std:: task:: { ready, Context , Poll } ;
1011
@@ -33,8 +34,13 @@ enum State<T> {
3334
3435cfg_io_blocking ! {
3536 impl <T > Blocking <T > {
37+ /// # Safety
38+ ///
39+ /// The `Read` implementation of `inner` must never read from the buffer
40+ /// it is borrowing and must correctly report the length of the data
41+ /// written into the buffer.
3642 #[ cfg_attr( feature = "fs" , allow( dead_code) ) ]
37- pub ( crate ) fn new( inner: T ) -> Blocking <T > {
43+ pub ( crate ) unsafe fn new( inner: T ) -> Blocking <T > {
3844 Blocking {
3945 inner: Some ( inner) ,
4046 state: State :: Idle ( Some ( Buf :: with_capacity( 0 ) ) ) ,
@@ -64,11 +70,12 @@ where
6470 return Poll :: Ready ( Ok ( ( ) ) ) ;
6571 }
6672
67- buf. ensure_capacity_for ( dst, DEFAULT_MAX_BUF_SIZE ) ;
6873 let mut inner = self . inner . take ( ) . unwrap ( ) ;
6974
75+ let max_buf_size = cmp:: min ( dst. remaining ( ) , DEFAULT_MAX_BUF_SIZE ) ;
7076 self . state = State :: Busy ( sys:: run ( move || {
71- let res = buf. read_from ( & mut inner) ;
77+ // SAFETY: the requirements are satisfied by `Blocking::new`.
78+ let res = unsafe { buf. read_from ( & mut inner, max_buf_size) } ;
7279 ( res, buf, inner)
7380 } ) ) ;
7481 }
@@ -227,25 +234,30 @@ impl Buf {
227234 & self . buf [ self . pos ..]
228235 }
229236
230- pub ( crate ) fn ensure_capacity_for ( & mut self , bytes : & ReadBuf < ' _ > , max_buf_size : usize ) {
237+ /// # Safety
238+ ///
239+ /// `rd` must not read from the buffer `read` is borrowing and must correctly
240+ /// report the length of the data written into the buffer.
241+ pub ( crate ) unsafe fn read_from < T : Read > (
242+ & mut self ,
243+ rd : & mut T ,
244+ max_buf_size : usize ,
245+ ) -> io:: Result < usize > {
231246 assert ! ( self . is_empty( ) ) ;
247+ self . buf . reserve ( max_buf_size) ;
232248
233- let len = cmp:: min ( bytes. remaining ( ) , max_buf_size) ;
234-
235- if self . buf . len ( ) < len {
236- self . buf . reserve ( len - self . buf . len ( ) ) ;
237- }
238-
239- unsafe {
240- self . buf . set_len ( len) ;
241- }
242- }
243-
244- pub ( crate ) fn read_from < T : Read > ( & mut self , rd : & mut T ) -> io:: Result < usize > {
245- let res = uninterruptibly ! ( rd. read( & mut self . buf) ) ;
249+ let buf = & mut self . buf . spare_capacity_mut ( ) [ ..max_buf_size] ;
250+ // SAFETY: The memory may be uninitialized, but `rd.read` will only write to the buffer.
251+ let buf = unsafe { & mut * ( buf as * mut [ MaybeUninit < u8 > ] as * mut [ u8 ] ) } ;
252+ let res = uninterruptibly ! ( rd. read( buf) ) ;
246253
247254 if let Ok ( n) = res {
248- self . buf . truncate ( n) ;
255+ // SAFETY: the caller promises that `rd.read` initializes
256+ // a section of `buf` and correctly reports that length.
257+ // The `self.is_empty()` assertion verifies that `n`
258+ // equals the length of the `buf` capacity that was written
259+ // to (and that `buf` isn't being shrunk).
260+ unsafe { self . buf . set_len ( n) }
249261 } else {
250262 self . buf . clear ( ) ;
251263 }
0 commit comments