zvariant/
fd.rs

1use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
2use std::os::fd::{self, AsFd, AsRawFd, BorrowedFd, RawFd};
3
4use crate::{Basic, Type};
5
6/// A file-descriptor type wrapper.
7///
8/// Since [`std::os::fd::BorrowedFd`] and [`std::os::fd::OwnedFd`] types
9/// do not implement  [`Serialize`] and [`Deserialize`]. So we provide a
10/// wrapper for both that implements these traits.
11///
12/// [`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html
13/// [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html
14#[derive(Debug)]
15pub enum Fd<'f> {
16    Borrowed(BorrowedFd<'f>),
17    Owned(fd::OwnedFd),
18}
19
20impl Fd<'_> {
21    /// Try to create an owned version of `self`.
22    pub fn try_to_owned(&self) -> crate::Result<Fd<'static>> {
23        self.as_fd()
24            .try_clone_to_owned()
25            .map(Fd::Owned)
26            .map_err(Into::into)
27    }
28
29    /// Try to clone `self`.
30    pub fn try_clone(&self) -> crate::Result<Self> {
31        Ok(match self {
32            Self::Borrowed(fd) => Self::Borrowed(*fd),
33            Self::Owned(fd) => Self::Owned(fd.try_clone()?),
34        })
35    }
36}
37
38impl<'f> From<BorrowedFd<'f>> for Fd<'f> {
39    fn from(fd: BorrowedFd<'f>) -> Self {
40        Self::Borrowed(fd)
41    }
42}
43
44impl From<fd::OwnedFd> for Fd<'_> {
45    fn from(fd: fd::OwnedFd) -> Self {
46        Self::Owned(fd)
47    }
48}
49
50impl From<OwnedFd> for Fd<'_> {
51    fn from(owned: OwnedFd) -> Self {
52        owned.inner
53    }
54}
55
56impl TryFrom<Fd<'_>> for fd::OwnedFd {
57    type Error = crate::Error;
58
59    fn try_from(fd: Fd<'_>) -> crate::Result<Self> {
60        match fd {
61            Fd::Borrowed(fd) => fd.try_clone_to_owned().map_err(Into::into),
62            Fd::Owned(fd) => Ok(fd),
63        }
64    }
65}
66
67impl AsRawFd for Fd<'_> {
68    fn as_raw_fd(&self) -> RawFd {
69        self.as_fd().as_raw_fd()
70    }
71}
72
73impl AsFd for Fd<'_> {
74    fn as_fd(&self) -> BorrowedFd<'_> {
75        match self {
76            Self::Borrowed(fd) => fd.as_fd(),
77            Self::Owned(fd) => fd.as_fd(),
78        }
79    }
80}
81
82impl<'fd, T> From<&'fd T> for Fd<'fd>
83where
84    T: AsFd,
85{
86    fn from(t: &'fd T) -> Self {
87        Self::Borrowed(t.as_fd())
88    }
89}
90
91impl std::fmt::Display for Fd<'_> {
92    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93        self.as_raw_fd().fmt(f)
94    }
95}
96
97macro_rules! fd_impl {
98    ($i:ty) => {
99        impl Basic for $i {
100            const SIGNATURE_CHAR: char = 'h';
101            const SIGNATURE_STR: &'static str = "h";
102        }
103
104        impl Type for $i {
105            const SIGNATURE: &'static crate::Signature = &crate::Signature::Fd;
106        }
107    };
108}
109
110fd_impl!(Fd<'_>);
111
112impl Serialize for Fd<'_> {
113    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
114    where
115        S: Serializer,
116    {
117        serializer.serialize_i32(self.as_raw_fd())
118    }
119}
120
121impl<'de> Deserialize<'de> for Fd<'de> {
122    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123    where
124        D: Deserializer<'de>,
125    {
126        let raw = i32::deserialize(deserializer)?;
127        // SAFETY: The `'de` lifetimes will ensure the borrow won't outlive the raw FD.
128        let fd = unsafe { BorrowedFd::borrow_raw(raw) };
129
130        Ok(Fd::Borrowed(fd))
131    }
132}
133
134impl PartialEq for Fd<'_> {
135    fn eq(&self, other: &Self) -> bool {
136        self.as_raw_fd().eq(&other.as_raw_fd())
137    }
138}
139impl Eq for Fd<'_> {}
140
141impl PartialOrd for Fd<'_> {
142    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
143        Some(self.cmp(other))
144    }
145}
146
147impl Ord for Fd<'_> {
148    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
149        self.as_raw_fd().cmp(&other.as_raw_fd())
150    }
151}
152
153impl std::hash::Hash for Fd<'_> {
154    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
155        self.as_raw_fd().hash(state)
156    }
157}
158
159/// A file-descriptor type wrapper.
160///
161/// This is the same as [`Fd`] type, except it only keeps an owned file descriptor.
162#[derive(Debug, PartialEq, Eq, Hash)]
163pub struct OwnedFd {
164    inner: Fd<'static>,
165}
166
167fd_impl!(OwnedFd);
168
169impl Serialize for OwnedFd {
170    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
171    where
172        S: Serializer,
173    {
174        self.inner.serialize(serializer)
175    }
176}
177
178impl<'de> Deserialize<'de> for OwnedFd {
179    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
180    where
181        D: Deserializer<'de>,
182    {
183        let fd = Fd::deserialize(deserializer)?;
184        Ok(OwnedFd {
185            inner: fd
186                .as_fd()
187                .try_clone_to_owned()
188                .map(Fd::Owned)
189                .map_err(D::Error::custom)?,
190        })
191    }
192}
193
194impl AsFd for OwnedFd {
195    fn as_fd(&self) -> BorrowedFd<'_> {
196        self.inner.as_fd()
197    }
198}
199
200impl AsRawFd for OwnedFd {
201    fn as_raw_fd(&self) -> RawFd {
202        self.inner.as_raw_fd()
203    }
204}
205
206impl From<fd::OwnedFd> for OwnedFd {
207    fn from(value: fd::OwnedFd) -> Self {
208        Self {
209            inner: Fd::Owned(value),
210        }
211    }
212}
213
214impl From<OwnedFd> for fd::OwnedFd {
215    fn from(value: OwnedFd) -> fd::OwnedFd {
216        match value.inner {
217            Fd::Owned(fd) => fd,
218            Fd::Borrowed(_) => unreachable!(),
219        }
220    }
221}
222
223impl From<Fd<'static>> for OwnedFd {
224    fn from(value: Fd<'static>) -> Self {
225        Self { inner: value }
226    }
227}
228
229impl std::fmt::Display for OwnedFd {
230    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231        self.inner.fmt(f)
232    }
233}