Skip to main content

dope_core/io/
fd.rs

1use std::fmt::{Debug, Formatter, Result};
2use std::marker::PhantomData;
3use std::mem::ManuallyDrop;
4
5use o3::marker::ThreadBound;
6
7use crate::backend::Backend;
8use crate::driver::DriverRef;
9use crate::driver::ready::ReadyHandle;
10
11#[derive(Clone, Copy, Debug)]
12pub struct FdSlot(u32, ThreadBound);
13
14impl FdSlot {
15    pub fn new(index: u32) -> Self {
16        Self(index, ThreadBound::NEW)
17    }
18
19    pub fn raw(self) -> u32 {
20        self.0
21    }
22}
23
24pub struct Fd<'d> {
25    slot: FdSlot,
26    driver: DriverRef<'d>,
27}
28
29pub struct FdGuard<'a, 'd> {
30    backend: &'a mut Backend,
31    slot: FdSlot,
32    driver: DriverRef<'d>,
33    _invariant: PhantomData<fn(&'d ()) -> &'d ()>,
34}
35
36impl Debug for Fd<'_> {
37    fn fmt(&self, formatter: &mut Formatter<'_>) -> Result {
38        formatter.debug_tuple("Fd").field(&self.slot.0).finish()
39    }
40}
41
42impl<'d> Fd<'d> {
43    /// # Safety
44    /// `slot` must be reserved from `driver` and uniquely owned.
45    #[inline]
46    pub unsafe fn from_raw_slot(slot: FdSlot, driver: DriverRef<'d>) -> Self {
47        Self { slot, driver }
48    }
49
50    pub fn slot(&self) -> FdSlot {
51        self.slot
52    }
53
54    #[inline]
55    pub fn index(&self) -> u32 {
56        self.slot.0
57    }
58
59    pub fn driver(&self) -> DriverRef<'d> {
60        self.driver
61    }
62
63    pub fn ready_handle(&self) -> ReadyHandle<'d> {
64        self.driver.fixed_ready(self.slot)
65    }
66
67    pub(crate) fn into_parts(self) -> (FdSlot, DriverRef<'d>) {
68        (self.slot, self.driver)
69    }
70}
71
72impl<'a, 'd> FdGuard<'a, 'd> {
73    pub(crate) fn new(backend: &'a mut Backend, slot: FdSlot, driver: DriverRef<'d>) -> Self {
74        Self {
75            backend,
76            slot,
77            driver,
78            _invariant: PhantomData,
79        }
80    }
81
82    pub fn slot(&self) -> FdSlot {
83        self.slot
84    }
85
86    pub fn persist(self) -> Fd<'d> {
87        let this = ManuallyDrop::new(self);
88        Fd {
89            slot: this.slot,
90            driver: this.driver,
91        }
92    }
93}
94
95impl Drop for FdGuard<'_, '_> {
96    fn drop(&mut self) {
97        self.backend.close_fd(self.slot);
98    }
99}