@@ -11,7 +11,7 @@ use miow::iocp::{CompletionPort, CompletionStatus};
11
11
use miow:: pipe;
12
12
use winapi:: shared:: winerror:: { ERROR_BROKEN_PIPE , ERROR_PIPE_LISTENING } ;
13
13
use winapi:: um:: ioapiset:: CancelIoEx ;
14
- use winapi:: um:: minwinbase:: OVERLAPPED_ENTRY ;
14
+ use winapi:: um:: minwinbase:: { OVERLAPPED , OVERLAPPED_ENTRY } ;
15
15
16
16
use crate :: event:: Source ;
17
17
use crate :: sys:: windows:: { Event , Overlapped } ;
@@ -70,35 +70,64 @@ pub struct NamedPipe {
70
70
/// constants depend on it, see the `offset_constants` test.
71
71
#[ repr( C ) ]
72
72
struct Inner {
73
+ // NOTE: careful modifying the order of these three fields, the `ptr_from_*`
74
+ // methods depend on the layout!
73
75
connect : Overlapped ,
74
76
read : Overlapped ,
75
77
write : Overlapped ,
78
+ // END NOTE.
76
79
handle : pipe:: NamedPipe ,
77
80
connecting : AtomicBool ,
78
81
io : Mutex < Io > ,
79
82
pool : Mutex < BufferPool > ,
80
83
}
81
84
82
- /// Offsets from a pointer to `Inner` to the `connect`, `read` and `write`
83
- /// fields.
84
- const CONNECT_OFFSET : usize = 0 ;
85
- const READ_OFFSET : usize = CONNECT_OFFSET + size_of :: < Overlapped > ( ) ; // `connect` fields.
86
- const WRITE_OFFSET : usize = READ_OFFSET + size_of :: < Overlapped > ( ) ; // `read` fields.
85
+ impl Inner {
86
+ /// Converts a pointer to `Inner.connect` to a pointer to `Inner`.
87
+ ///
88
+ /// # Unsafety
89
+ ///
90
+ /// Caller must ensure `ptr` is pointing to `Inner.connect`.
91
+ unsafe fn ptr_from_conn_overlapped ( ptr : * mut OVERLAPPED ) -> * const Inner {
92
+ // `connect` is the first field, so the pointer are the same.
93
+ ptr. cast ( )
94
+ }
95
+
96
+ /// Same as [`ptr_from_conn_overlapped`] but for `Inner.read`.
97
+ unsafe fn ptr_from_read_overlapped ( ptr : * mut OVERLAPPED ) -> * const Inner {
98
+ // `read` is after `connect: Overlapped`.
99
+ ( ptr as usize + size_of :: < Overlapped > ( ) ) as * const Inner
100
+ }
101
+
102
+ /// Same as [`ptr_from_conn_overlapped`] but for `Inner.write`.
103
+ unsafe fn ptr_from_write_overlapped ( ptr : * mut OVERLAPPED ) -> * const Inner {
104
+ // `read` is after `connect: Overlapped` and `read: Overlapped`.
105
+ ( ptr as usize + ( 2 * size_of :: < Overlapped > ( ) ) ) as * const Inner
106
+ }
107
+ }
87
108
88
109
#[ test]
89
- fn offset_constants ( ) {
110
+ fn ptr_from ( ) {
90
111
use std:: mem:: ManuallyDrop ;
91
112
use std:: ptr;
92
113
93
114
let pipe = unsafe { ManuallyDrop :: new ( NamedPipe :: from_raw_handle ( ptr:: null_mut ( ) ) ) } ;
94
115
let inner: & Inner = & pipe. inner ;
95
- let base = inner as * const Inner as usize ;
96
- let connect = & inner. connect as * const Overlapped as usize ;
97
- assert_eq ! ( base + CONNECT_OFFSET , connect) ;
98
- let read = & inner. read as * const Overlapped as usize ;
99
- assert_eq ! ( base + READ_OFFSET , read) ;
100
- let write = & inner. write as * const Overlapped as usize ;
101
- assert_eq ! ( base + WRITE_OFFSET , write) ;
116
+ assert_eq ! (
117
+ inner as * const Inner ,
118
+ unsafe { Inner :: ptr_from_conn_overlapped( & inner. connect as * const _ as * mut OVERLAPPED ) } ,
119
+ "`ptr_from_conn_overlapped` incorrect"
120
+ ) ;
121
+ assert_eq ! (
122
+ inner as * const Inner ,
123
+ unsafe { Inner :: ptr_from_read_overlapped( & inner. read as * const _ as * mut OVERLAPPED ) } ,
124
+ "`ptr_from_read_overlapped` incorrect"
125
+ ) ;
126
+ assert_eq ! (
127
+ inner as * const Inner ,
128
+ unsafe { Inner :: ptr_from_write_overlapped( & inner. write as * const _ as * mut OVERLAPPED ) } ,
129
+ "`ptr_from_write_overlapped` incorrect"
130
+ ) ;
102
131
}
103
132
104
133
struct Io {
@@ -590,8 +619,7 @@ fn connect_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
590
619
// Acquire the `Arc<Inner>`. Note that we should be guaranteed that
591
620
// the refcount is available to us due to the `mem::forget` in
592
621
// `connect` above.
593
- let me =
594
- unsafe { Arc :: from_raw ( ( status. overlapped ( ) as usize - CONNECT_OFFSET ) as * mut Inner ) } ;
622
+ let me = unsafe { Arc :: from_raw ( Inner :: ptr_from_conn_overlapped ( status. overlapped ( ) ) ) } ;
595
623
596
624
// Flag ourselves as no longer using the `connect` overlapped instances.
597
625
let prev = me. connecting . swap ( false , SeqCst ) ;
@@ -617,7 +645,7 @@ fn read_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
617
645
// Acquire the `FromRawArc<Inner>`. Note that we should be guaranteed that
618
646
// the refcount is available to us due to the `mem::forget` in
619
647
// `schedule_read` above.
620
- let me = unsafe { Arc :: from_raw ( ( status. overlapped ( ) as usize - READ_OFFSET ) as * mut Inner ) } ;
648
+ let me = unsafe { Arc :: from_raw ( Inner :: ptr_from_read_overlapped ( status. overlapped ( ) ) ) } ;
621
649
622
650
// Move from the `Pending` to `Ok` state.
623
651
let mut io = me. io . lock ( ) . unwrap ( ) ;
@@ -649,7 +677,7 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
649
677
// Acquire the `Arc<Inner>`. Note that we should be guaranteed that
650
678
// the refcount is available to us due to the `mem::forget` in
651
679
// `schedule_write` above.
652
- let me = unsafe { Arc :: from_raw ( ( status. overlapped ( ) as usize - WRITE_OFFSET ) as * mut Inner ) } ;
680
+ let me = unsafe { Arc :: from_raw ( Inner :: ptr_from_write_overlapped ( status. overlapped ( ) ) ) } ;
653
681
654
682
// Make the state change out of `Pending`. If we wrote the entire buffer
655
683
// then we're writable again and otherwise we schedule another write.
0 commit comments