1
- // `mem::uninitialized` replaced with `mem::MaybeUninit`,
2
- // can't upgrade yet
3
- #![ allow( deprecated) ]
4
-
5
1
use std:: fmt:: { self , Write } ;
6
- use std:: mem;
2
+ use std:: mem:: { self , MaybeUninit } ;
7
3
8
4
#[ cfg( any( test, feature = "server" , feature = "ffi" ) ) ]
9
5
use bytes:: Bytes ;
@@ -115,17 +111,23 @@ impl Http1Transaction for Server {
115
111
// but we *never* read any of it until after httparse has assigned
116
112
// values into it. By not zeroing out the stack memory, this saves
117
113
// 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
+ } ;
119
118
{
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
+ } ;
121
123
trace ! (
122
124
"Request.parse([Header; {}], [u8; {}])" ,
123
125
headers. len( ) ,
124
126
buf. len( )
125
127
) ;
126
- let mut req = httparse:: Request :: new ( & mut headers ) ;
128
+ let mut req = httparse:: Request :: new ( & mut [ ] ) ;
127
129
let bytes = buf. as_ref ( ) ;
128
- match req. parse ( bytes) {
130
+ match req. parse_with_uninit_headers ( bytes, & mut headers ) {
129
131
Ok ( httparse:: Status :: Complete ( parsed_len) ) => {
130
132
trace ! ( "Request.parse Complete({})" , parsed_len) ;
131
133
len = parsed_len;
@@ -194,6 +196,8 @@ impl Http1Transaction for Server {
194
196
headers. reserve ( headers_len) ;
195
197
196
198
for header in & headers_indices[ ..headers_len] {
199
+ // SAFETY: array is valid up to `headers_len`
200
+ let header = unsafe { & * header. as_ptr ( ) } ;
197
201
let name = header_name ! ( & slice[ header. name. 0 ..header. name. 1 ] ) ;
198
202
let value = header_value ! ( slice. slice( header. value. 0 ..header. value. 1 ) ) ;
199
203
@@ -867,18 +871,24 @@ impl Http1Transaction for Client {
867
871
// Loop to skip information status code headers (100 Continue, etc).
868
872
loop {
869
873
// 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
+ } ;
871
878
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 ( ) } ;
874
882
trace ! (
875
883
"Response.parse([Header; {}], [u8; {}])" ,
876
884
headers. len( ) ,
877
885
buf. len( )
878
886
) ;
879
- let mut res = httparse:: Response :: new ( & mut headers ) ;
887
+ let mut res = httparse:: Response :: new ( & mut [ ] ) ;
880
888
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
+ {
882
892
Ok ( httparse:: Status :: Complete ( len) ) => {
883
893
trace ! ( "Response.parse Complete({})" , len) ;
884
894
let status = StatusCode :: from_u16 ( res. code . unwrap ( ) ) ?;
@@ -934,6 +944,8 @@ impl Http1Transaction for Client {
934
944
935
945
headers. reserve ( headers_len) ;
936
946
for header in & headers_indices[ ..headers_len] {
947
+ // SAFETY: array is valid up to `headers_len`
948
+ let header = unsafe { & * header. as_ptr ( ) } ;
937
949
let name = header_name ! ( & slice[ header. name. 0 ..header. name. 1 ] ) ;
938
950
let value = header_value ! ( slice. slice( header. value. 0 ..header. value. 1 ) ) ;
939
951
@@ -1288,7 +1300,7 @@ struct HeaderIndices {
1288
1300
fn record_header_indices (
1289
1301
bytes : & [ u8 ] ,
1290
1302
headers : & [ httparse:: Header < ' _ > ] ,
1291
- indices : & mut [ HeaderIndices ] ,
1303
+ indices : & mut [ MaybeUninit < HeaderIndices > ] ,
1292
1304
) -> Result < ( ) , crate :: error:: Parse > {
1293
1305
let bytes_ptr = bytes. as_ptr ( ) as usize ;
1294
1306
@@ -1299,10 +1311,19 @@ fn record_header_indices(
1299
1311
}
1300
1312
let name_start = header. name . as_ptr ( ) as usize - bytes_ptr;
1301
1313
let name_end = name_start + header. name . len ( ) ;
1302
- indices. name = ( name_start, name_end) ;
1303
1314
let value_start = header. value . as_ptr ( ) as usize - bytes_ptr;
1304
1315
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) ;
1306
1327
}
1307
1328
1308
1329
Ok ( ( ) )
0 commit comments