1use std::{
2 io,
3 net::{Shutdown, SocketAddr},
4 ptr::NonNull,
5 task::Waker,
6 time::Duration,
7};
8
9use bitmask_enum::bitmask;
10
11use crate::{Description, Handle, Interest};
12
13#[bitmask]
14pub enum FileMode {
15 Read,
16 Write,
17 Create,
18 Truncate,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
23pub enum OpenFlags<'a> {
24 None,
25 OpenFile(&'a str, FileMode),
27 Bind(&'a [SocketAddr]),
29 Connect(&'a [SocketAddr]),
31 Duration(Duration),
32 UserDefined(&'a [u8]),
33}
34
35impl<'a> OpenFlags<'a> {
36 pub fn try_into_open_file(self) -> io::Result<(&'a str, FileMode)> {
37 match self {
38 Self::OpenFile(path, mode) => Ok((path, mode)),
39 _ => Err(io::Error::new(
40 io::ErrorKind::InvalidInput,
41 format!("Expect OpenFile, but got {:?}", self),
42 )),
43 }
44 }
45
46 pub fn try_into_bind(self) -> io::Result<&'a [SocketAddr]> {
47 match self {
48 Self::Bind(laddrs) => Ok(laddrs),
49 _ => Err(io::Error::new(
50 io::ErrorKind::InvalidInput,
51 format!("Expect Bind, but got {:?}", self),
52 )),
53 }
54 }
55
56 pub fn try_into_connect(self) -> io::Result<&'a [SocketAddr]> {
57 match self {
58 Self::Connect(raddrs) => Ok(raddrs),
59 _ => Err(io::Error::new(
60 io::ErrorKind::InvalidInput,
61 format!("Expect Bind, but got {:?}", self),
62 )),
63 }
64 }
65
66 pub fn try_into_duration(self) -> io::Result<Duration> {
67 match self {
68 Self::Duration(duration) => Ok(duration),
69 _ => Err(io::Error::new(
70 io::ErrorKind::InvalidInput,
71 format!("Expect Bind, but got {:?}", self),
72 )),
73 }
74 }
75
76 pub fn try_into_user_defined(self) -> io::Result<&'a [u8]> {
77 match self {
78 Self::UserDefined(buf) => Ok(buf),
79 _ => Err(io::Error::new(
80 io::ErrorKind::InvalidInput,
81 format!("Expect UserDefined, but got {:?}", self),
82 )),
83 }
84 }
85}
86
87#[derive(Debug)]
89pub enum Cmd<'a> {
90 Read {
92 waker: Waker,
93 buf: &'a mut [u8],
94 },
95 Write {
97 waker: Waker,
98 buf: &'a [u8],
99 },
100
101 SendTo {
103 waker: Waker,
104 buf: &'a [u8],
105 raddr: SocketAddr,
106 },
107
108 RecvFrom {
110 waker: Waker,
111 buf: &'a mut [u8],
112 },
113
114 Register {
116 source: Handle,
117 interests: Interest,
118 },
119
120 ReRegister {
122 source: Handle,
123 interests: Interest,
124 },
125
126 Accept(Waker),
131
132 PollOnce(Option<Duration>),
134
135 TryClone,
137 Timeout(Waker),
138 LocalAddr,
139 RemoteAddr,
140
141 Shutdown(Shutdown),
142}
143
144#[derive(Debug, Clone)]
146pub enum CmdResp {
147 None,
148 RecvFrom(usize, SocketAddr),
150 Incoming(Handle, SocketAddr),
152 DataLen(usize),
154 Timeout(bool),
155 Cloned(Handle),
157 SockAddr(SocketAddr),
158}
159
160impl CmdResp {
161 pub fn try_into_incoming(self) -> io::Result<(Handle, SocketAddr)> {
162 match self {
163 Self::Incoming(handle, raddr) => Ok((handle, raddr)),
164 _ => Err(io::Error::new(
165 io::ErrorKind::InvalidInput,
166 format!("Expect Incoming, but got {:?}", self),
167 )),
168 }
169 }
170
171 pub fn try_into_recv_from(self) -> io::Result<(usize, SocketAddr)> {
172 match self {
173 Self::RecvFrom(len, raddr) => Ok((len, raddr)),
174 _ => Err(io::Error::new(
175 io::ErrorKind::InvalidInput,
176 format!("Expect Incoming, but got {:?}", self),
177 )),
178 }
179 }
180
181 pub fn try_into_sockaddr(self) -> io::Result<SocketAddr> {
182 match self {
183 Self::SockAddr(addr) => Ok(addr),
184 _ => Err(io::Error::new(
185 io::ErrorKind::InvalidInput,
186 format!("Expect SockAddr, but got {:?}", self),
187 )),
188 }
189 }
190
191 pub fn try_into_datalen(self) -> io::Result<usize> {
192 match self {
193 Self::DataLen(len) => Ok(len),
194 _ => Err(io::Error::new(
195 io::ErrorKind::InvalidInput,
196 format!("Expect SockAddr, but got {:?}", self),
197 )),
198 }
199 }
200
201 pub fn try_into_timeout(self) -> io::Result<bool> {
202 match self {
203 Self::Timeout(status) => Ok(status),
204 _ => Err(io::Error::new(
205 io::ErrorKind::InvalidInput,
206 format!("Expect Timeout, but got {:?}", self),
207 )),
208 }
209 }
210}
211
212pub trait RawDriver {
214 fn fd_open(&self, desc: Description, open_flags: OpenFlags) -> io::Result<Handle>;
216
217 fn fd_cntl(&self, handle: Handle, cmd: Cmd) -> io::Result<CmdResp>;
219
220 fn fd_close(&self, handle: Handle) -> io::Result<()>;
226}
227
228#[repr(C)]
229#[derive(Clone)]
230struct DriverVTable {
231 fd_open: unsafe fn(NonNull<DriverVTable>, Description, OpenFlags) -> io::Result<Handle>,
232 fd_cntl: unsafe fn(NonNull<DriverVTable>, Handle, Cmd) -> io::Result<CmdResp>,
233 fd_close: unsafe fn(NonNull<DriverVTable>, Handle) -> io::Result<()>,
234 clone: unsafe fn(NonNull<DriverVTable>) -> Driver,
235 drop: unsafe fn(NonNull<DriverVTable>),
236}
237
238impl DriverVTable {
239 fn new<R: RawDriver + Clone>() -> Self {
240 fn fd_open<R: RawDriver + Clone>(
241 ptr: NonNull<DriverVTable>,
242 desc: Description,
243 flags: OpenFlags,
244 ) -> io::Result<Handle> {
245 let header = ptr.cast::<DriverHeader<R>>();
246
247 unsafe { header.as_ref().data.fd_open(desc, flags) }
248 }
249
250 fn fd_cntl<R: RawDriver + Clone>(
251 ptr: NonNull<DriverVTable>,
252 handle: Handle,
253 cmd: Cmd,
254 ) -> io::Result<CmdResp> {
255 let header = ptr.cast::<DriverHeader<R>>();
256
257 let result = unsafe { header.as_ref().data.fd_cntl(handle, cmd) };
258
259 result
262 }
263
264 fn fd_close<R: RawDriver + Clone>(
265 ptr: NonNull<DriverVTable>,
266 handle: Handle,
267 ) -> io::Result<()> {
268 let header = ptr.cast::<DriverHeader<R>>();
269
270 unsafe { header.as_ref().data.fd_close(handle) }
271 }
272
273 fn clone<R: RawDriver + Clone>(ptr: NonNull<DriverVTable>) -> Driver {
274 let driver = unsafe { ptr.cast::<DriverHeader<R>>().as_ref().clone() };
275
276 let ptr = unsafe {
277 NonNull::new_unchecked(Box::into_raw(Box::new(driver)) as *mut DriverVTable)
278 };
279
280 Driver { ptr }
281 }
282
283 fn drop<R: RawDriver + Clone>(ptr: NonNull<DriverVTable>) {
284 _ = unsafe { Box::from_raw(ptr.cast::<DriverHeader<R>>().as_ptr()) };
285 }
286
287 Self {
288 fd_open: fd_open::<R>,
289 fd_cntl: fd_cntl::<R>,
290 fd_close: fd_close::<R>,
291 clone: clone::<R>,
292 drop: drop::<R>,
293 }
294 }
295}
296
297pub trait IntoRawDriver {
298 type Driver: RawDriver + Clone;
299 fn into_raw_driver(self) -> Self::Driver;
300}
301
302#[repr(C)]
303#[derive(Clone)]
304struct DriverHeader<R: RawDriver + Clone> {
305 vtable: DriverVTable,
306 data: R,
307}
308
309#[derive(Debug)]
311pub struct Driver {
312 ptr: NonNull<DriverVTable>,
313}
314
315unsafe impl Send for Driver {}
316unsafe impl Sync for Driver {}
317
318impl<R: RawDriver + Clone> From<R> for Driver {
319 fn from(value: R) -> Self {
320 Self::new(value)
321 }
322}
323
324impl Driver {
325 pub fn new<R: RawDriver + Clone>(raw: R) -> Self {
327 let boxed = Box::new(DriverHeader::<R> {
328 data: raw,
329 vtable: DriverVTable::new::<R>(),
330 });
331
332 let ptr = unsafe { NonNull::new_unchecked(Box::into_raw(boxed) as *mut DriverVTable) };
333
334 Self { ptr }
335 }
336
337 pub fn fd_open(&self, desc: Description, open_flags: OpenFlags) -> io::Result<Handle> {
339 unsafe { (self.ptr.as_ref().fd_open)(self.ptr, desc, open_flags) }
340 }
341
342 pub fn fd_cntl(&self, handle: Handle, cmd: Cmd) -> io::Result<CmdResp> {
344 unsafe { (self.ptr.as_ref().fd_cntl)(self.ptr, handle, cmd) }
345 }
346
347 pub fn fd_close(&self, handle: Handle) -> io::Result<()> {
353 unsafe { (self.ptr.as_ref().fd_close)(self.ptr, handle) }
354 }
355}
356
357impl Clone for Driver {
358 fn clone(&self) -> Self {
359 unsafe { (self.ptr.as_ref().clone)(self.ptr) }
360 }
361}
362
363impl Drop for Driver {
364 fn drop(&mut self) {
365 unsafe { (self.ptr.as_ref().drop)(self.ptr) }
366 }
367}
368
369#[cfg(test)]
370mod tests {
371 use super::*;
372
373 #[derive(Clone)]
374 struct MockDriver {}
375
376 struct MockFile {}
377
378 impl RawDriver for MockDriver {
379 fn fd_open(
380 &self,
381 desc: crate::Description,
382 _open_flags: crate::OpenFlags,
383 ) -> std::io::Result<crate::Handle> {
384 Ok(Handle::from((desc, MockFile {})))
385 }
386
387 fn fd_cntl(
388 &self,
389 _handle: crate::Handle,
390 _cmd: crate::Cmd,
391 ) -> std::io::Result<crate::CmdResp> {
392 Ok(CmdResp::None)
393 }
394
395 fn fd_close(&self, handle: crate::Handle) -> std::io::Result<()> {
396 handle.drop_as::<MockFile>();
397
398 Ok(())
399 }
400 }
401
402 #[test]
403 fn test_driver_vtable() {
404 let driver = Driver::new(MockDriver {});
405
406 let driver = driver.clone();
407
408 let handle = driver.fd_open(Description::File, OpenFlags::None).unwrap();
409
410 driver.fd_cntl(handle, Cmd::PollOnce(None)).unwrap();
411
412 driver.fd_close(handle).unwrap();
413 }
414}