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