2
2
3
3
#![ cfg_attr( not( doc) , no_std) ]
4
4
#![ feature( doc_auto_cfg) ]
5
+ #![ feature( maybe_uninit_slice) ]
5
6
6
7
#[ cfg( feature = "alloc" ) ]
7
8
extern crate alloc;
@@ -22,6 +23,107 @@ use alloc::{string::String, vec::Vec};
22
23
23
24
use axerrno:: ax_err;
24
25
26
+ /// Default [`Read::read_to_end`] implementation with optional size hint.
27
+ ///
28
+ /// Adapted from [`std::io::default_read_to_end`].
29
+ ///
30
+ /// [`std::io::default_read_to_end`]: https://github.com/rust-lang/rust/blob/30f168ef811aec63124eac677e14699baa9395bd/library/std/src/io/mod.rs#L409
31
+ #[ cfg( feature = "alloc" ) ]
32
+ pub fn default_read_to_end < R : Read + ?Sized > (
33
+ r : & mut R ,
34
+ buf : & mut Vec < u8 > ,
35
+ size_hint : Option < usize > ,
36
+ ) -> Result < usize > {
37
+ const DEFAULT_BUF_SIZE : usize = 1024 ;
38
+
39
+ let start_len = buf. len ( ) ;
40
+ let start_cap = buf. capacity ( ) ;
41
+ // Optionally limit the maximum bytes read on each iteration.
42
+ // This adds an arbitrary fiddle factor to allow for more data than we expect.
43
+ let mut max_read_size = size_hint
44
+ . and_then ( |s| {
45
+ s. checked_add ( 1024 ) ?
46
+ . checked_next_multiple_of ( DEFAULT_BUF_SIZE )
47
+ } )
48
+ . unwrap_or ( DEFAULT_BUF_SIZE ) ;
49
+
50
+ const PROBE_SIZE : usize = 32 ;
51
+
52
+ fn small_probe_read < R : Read + ?Sized > ( r : & mut R , buf : & mut Vec < u8 > ) -> Result < usize > {
53
+ let mut probe = [ 0u8 ; PROBE_SIZE ] ;
54
+
55
+ let n = r. read ( & mut probe) ?;
56
+ buf. extend_from_slice ( & probe[ ..n] ) ;
57
+ Ok ( n)
58
+ }
59
+
60
+ if ( size_hint. is_none ( ) || size_hint == Some ( 0 ) ) && buf. capacity ( ) - buf. len ( ) < PROBE_SIZE {
61
+ let read = small_probe_read ( r, buf) ?;
62
+
63
+ if read == 0 {
64
+ return Ok ( 0 ) ;
65
+ }
66
+ }
67
+
68
+ let mut initialized = 0 ; // Extra initialized bytes from previous loop iteration
69
+
70
+ loop {
71
+ if buf. len ( ) == buf. capacity ( ) && buf. capacity ( ) == start_cap {
72
+ // The buffer might be an exact fit. Let's read into a probe buffer
73
+ // and see if it returns `Ok(0)`. If so, we've avoided an
74
+ // unnecessary doubling of the capacity. But if not, append the
75
+ // probe buffer to the primary buffer and let its capacity grow.
76
+ let read = small_probe_read ( r, buf) ?;
77
+
78
+ if read == 0 {
79
+ return Ok ( buf. len ( ) - start_len) ;
80
+ }
81
+ }
82
+
83
+ if buf. len ( ) == buf. capacity ( ) {
84
+ // buf is full, need more space
85
+ if let Err ( e) = buf. try_reserve ( PROBE_SIZE ) {
86
+ return ax_err ! ( NoMemory , e) ;
87
+ }
88
+ }
89
+
90
+ let mut spare = buf. spare_capacity_mut ( ) ;
91
+ let buf_len = spare. len ( ) . min ( max_read_size) ;
92
+ spare = & mut spare[ ..buf_len] ;
93
+
94
+ let uninit = & mut spare[ initialized..] ;
95
+ // SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
96
+ // since it is comes from a slice reference.
97
+ unsafe {
98
+ core:: ptr:: write_bytes ( uninit. as_mut_ptr ( ) , 0 , uninit. len ( ) ) ;
99
+ }
100
+
101
+ // SAFETY: spare is fully initialized
102
+ let unfilled = unsafe { spare. assume_init_mut ( ) } ;
103
+
104
+ let bytes_read = r. read ( unfilled) ?;
105
+ // SAFETY: bytes_read is guaranteed to be less than or equal to spare.len()
106
+ unsafe {
107
+ let new_len = buf. len ( ) + bytes_read;
108
+ buf. set_len ( new_len) ;
109
+ }
110
+
111
+ if bytes_read == 0 {
112
+ return Ok ( buf. len ( ) - start_len) ;
113
+ }
114
+
115
+ initialized = buf_len - bytes_read;
116
+
117
+ if size_hint. is_none ( ) {
118
+ // we have passed a larger buffer than previously and the
119
+ // reader still hasn't returned a short read
120
+ if buf_len >= max_read_size && bytes_read == buf_len {
121
+ max_read_size = max_read_size. saturating_mul ( 2 ) ;
122
+ }
123
+ }
124
+ }
125
+ }
126
+
25
127
/// The `Read` trait allows for reading bytes from a source.
26
128
pub trait Read {
27
129
/// Pull some bytes from this source into the specified buffer, returning
@@ -31,15 +133,7 @@ pub trait Read {
31
133
/// Read all bytes until EOF in this source, placing them into `buf`.
32
134
#[ cfg( feature = "alloc" ) ]
33
135
fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
34
- let start_len = buf. len ( ) ;
35
- let mut probe = [ 0u8 ; 32 ] ;
36
- loop {
37
- match self . read ( & mut probe) {
38
- Ok ( 0 ) => return Ok ( buf. len ( ) - start_len) ,
39
- Ok ( n) => buf. extend_from_slice ( & probe[ ..n] ) ,
40
- Err ( e) => return Err ( e) ,
41
- }
42
- }
136
+ default_read_to_end ( self , buf, None )
43
137
}
44
138
45
139
/// Read all bytes until EOF in this source, appending them to `buf`.
0 commit comments