zvariant/
fd.rs

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