1use std::{io, marker::PhantomData, mem::MaybeUninit, pin::Pin, task::Waker};
2
3use compio_buf::BufResult;
4
5use crate::{OpCode, Overlapped, PushEntry, RawFd};
6
7#[repr(C)]
15pub(crate) struct RawOp<T: ?Sized> {
16 header: Overlapped,
17 cancelled: bool,
21 metadata: usize,
23 result: PushEntry<Option<Waker>, io::Result<usize>>,
24 flags: u32,
25 op: T,
26}
27
28#[repr(C)]
29union OpCodePtrRepr {
30 ptr: *mut RawOp<dyn OpCode>,
31 components: OpCodePtrComponents,
32}
33
34#[repr(C)]
35#[derive(Clone, Copy)]
36struct OpCodePtrComponents {
37 data_pointer: *mut (),
38 metadata: usize,
39}
40
41fn opcode_metadata<T: OpCode + 'static>() -> usize {
42 let mut op = MaybeUninit::<RawOp<T>>::uninit();
43 unsafe {
45 OpCodePtrRepr {
46 ptr: op.as_mut_ptr(),
47 }
48 .components
49 .metadata
50 }
51}
52
53const unsafe fn opcode_dyn_mut(ptr: *mut (), metadata: usize) -> *mut RawOp<dyn OpCode> {
54 unsafe {
56 OpCodePtrRepr {
57 components: OpCodePtrComponents {
58 data_pointer: ptr,
59 metadata,
60 },
61 }
62 .ptr
63 }
64}
65
66#[derive(PartialEq, Eq, Hash)]
75pub struct Key<T: ?Sized> {
76 user_data: *mut (),
77 _p: PhantomData<Box<RawOp<T>>>,
78}
79
80impl<T: ?Sized> Unpin for Key<T> {}
81
82impl<T: OpCode + 'static> Key<T> {
83 pub(crate) fn new(driver: RawFd, op: T) -> Self {
85 let header = Overlapped::new(driver);
86 let raw_op = Box::new(RawOp {
87 header,
88 cancelled: false,
89 metadata: opcode_metadata::<T>(),
90 result: PushEntry::Pending(None),
91 flags: 0,
92 op,
93 });
94 unsafe { Self::new_unchecked(Box::into_raw(raw_op) as _) }
95 }
96}
97
98impl<T: ?Sized> Key<T> {
99 pub unsafe fn new_unchecked(user_data: usize) -> Self {
107 Self {
108 user_data: user_data as _,
109 _p: PhantomData,
110 }
111 }
112
113 pub fn user_data(&self) -> usize {
115 self.user_data as _
116 }
117
118 fn as_opaque(&self) -> &RawOp<()> {
119 unsafe { &*(self.user_data as *const RawOp<()>) }
121 }
122
123 fn as_opaque_mut(&mut self) -> &mut RawOp<()> {
124 unsafe { &mut *(self.user_data as *mut RawOp<()>) }
126 }
127
128 fn as_dyn_mut_ptr(&mut self) -> *mut RawOp<dyn OpCode> {
129 let user_data = self.user_data;
130 let this = self.as_opaque_mut();
131 unsafe { opcode_dyn_mut(user_data, this.metadata) }
133 }
134
135 #[cfg(windows)]
137 pub(crate) fn as_mut_ptr(&mut self) -> *mut Overlapped {
138 &mut self.as_opaque_mut().header
139 }
140
141 pub(crate) fn set_cancelled(&mut self) -> bool {
145 self.as_opaque_mut().cancelled = true;
146 self.has_result()
147 }
148
149 pub(crate) fn set_result(&mut self, res: io::Result<usize>) -> bool {
153 let this = unsafe { &mut *self.as_dyn_mut_ptr() };
154 #[cfg(io_uring)]
155 if let Ok(res) = res {
156 unsafe {
157 Pin::new_unchecked(&mut this.op).set_result(res);
158 }
159 }
160 if let PushEntry::Pending(Some(w)) =
161 std::mem::replace(&mut this.result, PushEntry::Ready(res))
162 {
163 w.wake();
164 }
165 this.cancelled
166 }
167
168 pub(crate) fn set_flags(&mut self, flags: u32) {
169 self.as_opaque_mut().flags = flags;
170 }
171
172 pub(crate) fn flags(&self) -> u32 {
173 self.as_opaque().flags
174 }
175
176 pub(crate) fn has_result(&self) -> bool {
178 self.as_opaque().result.is_ready()
179 }
180
181 pub(crate) fn set_waker(&mut self, waker: Waker) {
183 if let PushEntry::Pending(w) = &mut self.as_opaque_mut().result {
184 *w = Some(waker)
185 }
186 }
187
188 pub(crate) unsafe fn into_box(mut self) -> Box<RawOp<dyn OpCode>> {
197 unsafe { Box::from_raw(self.as_dyn_mut_ptr()) }
198 }
199}
200
201impl<T> Key<T> {
202 pub(crate) unsafe fn into_inner(self) -> BufResult<usize, T> {
208 let op = unsafe { Box::from_raw(self.user_data as *mut RawOp<T>) };
209 BufResult(unsafe { op.result.take_ready().unwrap_unchecked() }, op.op)
210 }
211}
212
213impl<T: OpCode + ?Sized> Key<T> {
214 pub(crate) fn as_op_pin(&mut self) -> Pin<&mut dyn OpCode> {
216 unsafe {
218 let this = &mut *self.as_dyn_mut_ptr();
219 Pin::new_unchecked(&mut this.op)
220 }
221 }
222
223 #[cfg(windows)]
228 pub(crate) fn operate_blocking(&mut self) -> io::Result<usize> {
229 use std::task::Poll;
230
231 let optr = self.as_mut_ptr();
232 let op = self.as_op_pin();
233 let res = unsafe { op.operate(optr.cast()) };
234 match res {
235 Poll::Pending => unreachable!("this operation is not overlapped"),
236 Poll::Ready(res) => res,
237 }
238 }
239}
240
241impl<T: ?Sized> std::fmt::Debug for Key<T> {
242 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243 write!(f, "Key({})", self.user_data())
244 }
245}