1- // `mem::uninitialized` replaced with `mem::MaybeUninit`,
2- // can't upgrade yet
3- #![ allow( deprecated) ]
4-
51use std:: fmt:: { self , Write } ;
6- use std:: mem;
2+ use std:: mem:: { self , MaybeUninit } ;
73
84#[ cfg( any( test, feature = "server" , feature = "ffi" ) ) ]
95use bytes:: Bytes ;
@@ -115,17 +111,23 @@ impl Http1Transaction for Server {
115111 // but we *never* read any of it until after httparse has assigned
116112 // values into it. By not zeroing out the stack memory, this saves
117113 // a good ~5% on pipeline benchmarks.
118- let mut headers_indices: [ HeaderIndices ; MAX_HEADERS ] = unsafe { mem:: uninitialized ( ) } ;
114+ let mut headers_indices: [ MaybeUninit < HeaderIndices > ; MAX_HEADERS ] = unsafe {
115+ // SAFETY: We can go safely from MaybeUninit array to array of MaybeUninit
116+ MaybeUninit :: uninit ( ) . assume_init ( )
117+ } ;
119118 {
120- let mut headers: [ httparse:: Header < ' _ > ; MAX_HEADERS ] = unsafe { mem:: uninitialized ( ) } ;
119+ /* SAFETY: it is safe to go from MaybeUninit array to array of MaybeUninit */
120+ let mut headers: [ MaybeUninit < httparse:: Header < ' _ > > ; MAX_HEADERS ] = unsafe {
121+ MaybeUninit :: uninit ( ) . assume_init ( )
122+ } ;
121123 trace ! (
122124 "Request.parse([Header; {}], [u8; {}])" ,
123125 headers. len( ) ,
124126 buf. len( )
125127 ) ;
126- let mut req = httparse:: Request :: new ( & mut headers ) ;
128+ let mut req = httparse:: Request :: new ( & mut [ ] ) ;
127129 let bytes = buf. as_ref ( ) ;
128- match req. parse ( bytes) {
130+ match req. parse_with_uninit_headers ( bytes, & mut headers ) {
129131 Ok ( httparse:: Status :: Complete ( parsed_len) ) => {
130132 trace ! ( "Request.parse Complete({})" , parsed_len) ;
131133 len = parsed_len;
@@ -194,6 +196,8 @@ impl Http1Transaction for Server {
194196 headers. reserve ( headers_len) ;
195197
196198 for header in & headers_indices[ ..headers_len] {
199+ // SAFETY: array is valid up to `headers_len`
200+ let header = unsafe { & * header. as_ptr ( ) } ;
197201 let name = header_name ! ( & slice[ header. name. 0 ..header. name. 1 ] ) ;
198202 let value = header_value ! ( slice. slice( header. value. 0 ..header. value. 1 ) ) ;
199203
@@ -867,18 +871,24 @@ impl Http1Transaction for Client {
867871 // Loop to skip information status code headers (100 Continue, etc).
868872 loop {
869873 // Unsafe: see comment in Server Http1Transaction, above.
870- let mut headers_indices: [ HeaderIndices ; MAX_HEADERS ] = unsafe { mem:: uninitialized ( ) } ;
874+ let mut headers_indices: [ MaybeUninit < HeaderIndices > ; MAX_HEADERS ] = unsafe {
875+ // SAFETY: We can go safely from MaybeUninit array to array of MaybeUninit
876+ MaybeUninit :: uninit ( ) . assume_init ( )
877+ } ;
871878 let ( len, status, reason, version, headers_len) = {
872- let mut headers: [ httparse:: Header < ' _ > ; MAX_HEADERS ] =
873- unsafe { mem:: uninitialized ( ) } ;
879+ // SAFETY: We can go safely from MaybeUninit array to array of MaybeUninit
880+ let mut headers: [ MaybeUninit < httparse:: Header < ' _ > > ; MAX_HEADERS ] =
881+ unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
874882 trace ! (
875883 "Response.parse([Header; {}], [u8; {}])" ,
876884 headers. len( ) ,
877885 buf. len( )
878886 ) ;
879- let mut res = httparse:: Response :: new ( & mut headers ) ;
887+ let mut res = httparse:: Response :: new ( & mut [ ] ) ;
880888 let bytes = buf. as_ref ( ) ;
881- match ctx. h1_parser_config . parse_response ( & mut res, bytes) {
889+ match ctx. h1_parser_config
890+ . parse_response_with_uninit_headers ( & mut res, bytes, & mut headers)
891+ {
882892 Ok ( httparse:: Status :: Complete ( len) ) => {
883893 trace ! ( "Response.parse Complete({})" , len) ;
884894 let status = StatusCode :: from_u16 ( res. code . unwrap ( ) ) ?;
@@ -934,6 +944,8 @@ impl Http1Transaction for Client {
934944
935945 headers. reserve ( headers_len) ;
936946 for header in & headers_indices[ ..headers_len] {
947+ // SAFETY: array is valid up to `headers_len`
948+ let header = unsafe { & * header. as_ptr ( ) } ;
937949 let name = header_name ! ( & slice[ header. name. 0 ..header. name. 1 ] ) ;
938950 let value = header_value ! ( slice. slice( header. value. 0 ..header. value. 1 ) ) ;
939951
@@ -1288,7 +1300,7 @@ struct HeaderIndices {
12881300fn record_header_indices (
12891301 bytes : & [ u8 ] ,
12901302 headers : & [ httparse:: Header < ' _ > ] ,
1291- indices : & mut [ HeaderIndices ] ,
1303+ indices : & mut [ MaybeUninit < HeaderIndices > ] ,
12921304) -> Result < ( ) , crate :: error:: Parse > {
12931305 let bytes_ptr = bytes. as_ptr ( ) as usize ;
12941306
@@ -1299,10 +1311,19 @@ fn record_header_indices(
12991311 }
13001312 let name_start = header. name . as_ptr ( ) as usize - bytes_ptr;
13011313 let name_end = name_start + header. name . len ( ) ;
1302- indices. name = ( name_start, name_end) ;
13031314 let value_start = header. value . as_ptr ( ) as usize - bytes_ptr;
13041315 let value_end = value_start + header. value . len ( ) ;
1305- indices. value = ( value_start, value_end) ;
1316+
1317+ // FIXME(maybe_uninit_extra)
1318+ // FIXME(addr_of)
1319+ // Currently we don't have `ptr::addr_of_mut` in stable rust or
1320+ // MaybeUninit::write, so this is some way of assigning into a MaybeUninit
1321+ // safely
1322+ let new_header_indices = HeaderIndices {
1323+ name : ( name_start, name_end) ,
1324+ value : ( value_start, value_end) ,
1325+ } ;
1326+ * indices = MaybeUninit :: new ( new_header_indices) ;
13061327 }
13071328
13081329 Ok ( ( ) )
0 commit comments