@@ -5,6 +5,7 @@ use std::cmp;
5
5
use std:: future:: Future ;
6
6
use std:: io;
7
7
use std:: io:: prelude:: * ;
8
+ use std:: mem:: MaybeUninit ;
8
9
use std:: pin:: Pin ;
9
10
use std:: task:: { ready, Context , Poll } ;
10
11
@@ -33,8 +34,13 @@ enum State<T> {
33
34
34
35
cfg_io_blocking ! {
35
36
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.
36
42
#[ 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 > {
38
44
Blocking {
39
45
inner: Some ( inner) ,
40
46
state: State :: Idle ( Some ( Buf :: with_capacity( 0 ) ) ) ,
@@ -64,11 +70,12 @@ where
64
70
return Poll :: Ready ( Ok ( ( ) ) ) ;
65
71
}
66
72
67
- buf. ensure_capacity_for ( dst, DEFAULT_MAX_BUF_SIZE ) ;
68
73
let mut inner = self . inner . take ( ) . unwrap ( ) ;
69
74
75
+ let max_buf_size = cmp:: min ( dst. remaining ( ) , DEFAULT_MAX_BUF_SIZE ) ;
70
76
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) } ;
72
79
( res, buf, inner)
73
80
} ) ) ;
74
81
}
@@ -227,25 +234,30 @@ impl Buf {
227
234
& self . buf [ self . pos ..]
228
235
}
229
236
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 > {
231
246
assert ! ( self . is_empty( ) ) ;
247
+ self . buf . reserve ( max_buf_size) ;
232
248
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) ) ;
246
253
247
254
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) }
249
261
} else {
250
262
self . buf . clear ( ) ;
251
263
}
0 commit comments