@@ -238,15 +238,6 @@ fn random_number() -> usize {
238
238
}
239
239
}
240
240
241
- // Abstracts over `ReadFileEx` and `WriteFileEx`
242
- type AlertableIoFn = unsafe extern "system" fn (
243
- BorrowedHandle < ' _ > ,
244
- * mut core:: ffi:: c_void ,
245
- u32 ,
246
- * mut c:: OVERLAPPED ,
247
- c:: LPOVERLAPPED_COMPLETION_ROUTINE ,
248
- ) -> c:: BOOL ;
249
-
250
241
impl AnonPipe {
251
242
pub fn handle ( & self ) -> & Handle {
252
243
& self . inner
@@ -262,7 +253,10 @@ impl AnonPipe {
262
253
pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
263
254
let result = unsafe {
264
255
let len = crate :: cmp:: min ( buf. len ( ) , u32:: MAX as usize ) as u32 ;
265
- self . alertable_io_internal ( c:: ReadFileEx , buf. as_mut_ptr ( ) as _ , len)
256
+ let ptr = buf. as_mut_ptr ( ) ;
257
+ self . alertable_io_internal ( |overlapped, callback| {
258
+ c:: ReadFileEx ( self . inner . as_raw_handle ( ) , ptr, len, overlapped, callback)
259
+ } )
266
260
} ;
267
261
268
262
match result {
@@ -278,7 +272,10 @@ impl AnonPipe {
278
272
pub fn read_buf ( & self , mut buf : BorrowedCursor < ' _ > ) -> io:: Result < ( ) > {
279
273
let result = unsafe {
280
274
let len = crate :: cmp:: min ( buf. capacity ( ) , u32:: MAX as usize ) as u32 ;
281
- self . alertable_io_internal ( c:: ReadFileEx , buf. as_mut ( ) . as_mut_ptr ( ) as _ , len)
275
+ let ptr = buf. as_mut ( ) . as_mut_ptr ( ) . cast :: < u8 > ( ) ;
276
+ self . alertable_io_internal ( |overlapped, callback| {
277
+ c:: ReadFileEx ( self . inner . as_raw_handle ( ) , ptr, len, overlapped, callback)
278
+ } )
282
279
} ;
283
280
284
281
match result {
@@ -313,7 +310,9 @@ impl AnonPipe {
313
310
pub fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
314
311
unsafe {
315
312
let len = crate :: cmp:: min ( buf. len ( ) , u32:: MAX as usize ) as u32 ;
316
- self . alertable_io_internal ( c:: WriteFileEx , buf. as_ptr ( ) as _ , len)
313
+ self . alertable_io_internal ( |overlapped, callback| {
314
+ c:: WriteFileEx ( self . inner . as_raw_handle ( ) , buf. as_ptr ( ) , len, overlapped, callback)
315
+ } )
317
316
}
318
317
}
319
318
@@ -341,12 +340,9 @@ impl AnonPipe {
341
340
/// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex
342
341
/// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex
343
342
/// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls
344
- #[ allow( unsafe_op_in_unsafe_fn) ]
345
343
unsafe fn alertable_io_internal (
346
344
& self ,
347
- io : AlertableIoFn ,
348
- buf : * mut core:: ffi:: c_void ,
349
- len : u32 ,
345
+ io : impl FnOnce ( & mut c:: OVERLAPPED , c:: LPOVERLAPPED_COMPLETION_ROUTINE ) -> c:: BOOL ,
350
346
) -> io:: Result < usize > {
351
347
// Use "alertable I/O" to synchronize the pipe I/O.
352
348
// This has four steps.
@@ -384,20 +380,25 @@ impl AnonPipe {
384
380
lpOverlapped : * mut c:: OVERLAPPED ,
385
381
) {
386
382
// Set `async_result` using a pointer smuggled through `hEvent`.
387
- let result =
388
- AsyncResult { error : dwErrorCode, transferred : dwNumberOfBytesTransferred } ;
389
- * ( * lpOverlapped) . hEvent . cast :: < Option < AsyncResult > > ( ) = Some ( result) ;
383
+ // SAFETY:
384
+ // At this point, the OVERLAPPED struct will have been written to by the OS,
385
+ // except for our `hEvent` field which we set to a valid AsyncResult pointer (see below)
386
+ unsafe {
387
+ let result =
388
+ AsyncResult { error : dwErrorCode, transferred : dwNumberOfBytesTransferred } ;
389
+ * ( * lpOverlapped) . hEvent . cast :: < Option < AsyncResult > > ( ) = Some ( result) ;
390
+ }
390
391
}
391
392
392
393
// STEP 1: Start the I/O operation.
393
- let mut overlapped: c:: OVERLAPPED = crate :: mem:: zeroed ( ) ;
394
+ let mut overlapped: c:: OVERLAPPED = unsafe { crate :: mem:: zeroed ( ) } ;
394
395
// `hEvent` is unused by `ReadFileEx` and `WriteFileEx`.
395
396
// Therefore the documentation suggests using it to smuggle a pointer to the callback.
396
397
overlapped. hEvent = core:: ptr:: addr_of_mut!( async_result) as * mut _ ;
397
398
398
399
// Asynchronous read of the pipe.
399
400
// If successful, `callback` will be called once it completes.
400
- let result = io ( self . inner . as_handle ( ) , buf , len , & mut overlapped, Some ( callback) ) ;
401
+ let result = io ( & mut overlapped, Some ( callback) ) ;
401
402
if result == c:: FALSE {
402
403
// We can return here because the call failed.
403
404
// After this we must not return until the I/O completes.
@@ -408,7 +409,7 @@ impl AnonPipe {
408
409
let result = loop {
409
410
// STEP 2: Enter an alertable state.
410
411
// The second parameter of `SleepEx` is used to make this sleep alertable.
411
- c:: SleepEx ( c:: INFINITE , c:: TRUE ) ;
412
+ unsafe { c:: SleepEx ( c:: INFINITE , c:: TRUE ) } ;
412
413
if let Some ( result) = async_result {
413
414
break result;
414
415
}
0 commit comments