Skip to main content

dope_core/io/
fd.rs

1use std::io;
2use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
3
4pub fn take_fd(fd: RawFd) -> FdHandle {
5    assert!(
6        fd >= 0,
7        "dope invariant violated: io result cannot be negative"
8    );
9    unsafe { FdHandle::from_raw(fd) }
10}
11
12#[derive(Clone, Copy, Debug)]
13pub struct Fd {
14    fd: RawFd,
15}
16
17impl Fd {
18    #[must_use]
19    pub const fn new(fd: RawFd) -> Self {
20        Self { fd }
21    }
22}
23
24impl AsRawFd for Fd {
25    fn as_raw_fd(&self) -> RawFd {
26        self.fd
27    }
28}
29
30#[derive(Clone, Copy, Debug)]
31pub struct FixedFd {
32    fd: RawFd,
33    fixed: u32,
34}
35
36impl FixedFd {
37    #[must_use]
38    pub const fn new(fd: RawFd, fixed: u32) -> Self {
39        Self { fd, fixed }
40    }
41
42    pub const fn fixed_index(self) -> u32 {
43        self.fixed
44    }
45
46    pub const fn as_fd(self) -> Fd {
47        Fd::new(self.fd)
48    }
49}
50
51#[derive(Debug)]
52pub struct FdHandle {
53    fd: OwnedFd,
54}
55
56impl FdHandle {
57    /// # Safety
58    /// `fd` must be a valid open file descriptor with no other owner.
59    #[must_use]
60    pub unsafe fn from_raw(fd: RawFd) -> Self {
61        Self {
62            fd: unsafe { OwnedFd::from_raw_fd(fd) },
63        }
64    }
65
66    #[must_use]
67    pub fn into_owned(self) -> OwnedFd {
68        self.fd
69    }
70
71    pub fn try_clone(&self) -> io::Result<Self> {
72        Ok(Self::from(self.fd.try_clone()?))
73    }
74
75    pub fn as_fd(&self) -> Fd {
76        Fd::new(self.fd.as_raw_fd())
77    }
78
79    pub fn fixed_io(&self, fixed: u32) -> FixedFd {
80        FixedFd::new(self.fd.as_raw_fd(), fixed)
81    }
82}
83
84impl From<OwnedFd> for FdHandle {
85    fn from(fd: OwnedFd) -> Self {
86        Self { fd }
87    }
88}
89
90impl AsRawFd for FdHandle {
91    fn as_raw_fd(&self) -> RawFd {
92        self.fd.as_raw_fd()
93    }
94}