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 #[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}