1 | use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; |
2 | use static_assertions::assert_impl_all; |
3 | use std::os::fd::{self, AsFd, AsRawFd, BorrowedFd, RawFd}; |
4 | |
5 | use 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)] |
16 | pub enum Fd<'f> { |
17 | Borrowed(BorrowedFd<'f>), |
18 | Owned(fd::OwnedFd), |
19 | } |
20 | |
21 | impl<'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(op: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: &BorrowedFd<'f>) => Self::Borrowed(*fd), |
34 | Self::Owned(fd: &OwnedFd) => Self::Owned(fd.try_clone()?), |
35 | }) |
36 | } |
37 | } |
38 | |
39 | impl<'f> From<BorrowedFd<'f>> for Fd<'f> { |
40 | fn from(fd: BorrowedFd<'f>) -> Self { |
41 | Self::Borrowed(fd) |
42 | } |
43 | } |
44 | |
45 | impl From<fd::OwnedFd> for Fd<'_> { |
46 | fn from(fd: fd::OwnedFd) -> Self { |
47 | Self::Owned(fd) |
48 | } |
49 | } |
50 | |
51 | impl From<OwnedFd> for Fd<'_> { |
52 | fn from(owned: OwnedFd) -> Self { |
53 | owned.inner |
54 | } |
55 | } |
56 | |
57 | impl 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: BorrowedFd<'_>) => fd.try_clone_to_owned().map_err(op:Into::into), |
63 | Fd::Owned(fd: OwnedFd) => Ok(fd), |
64 | } |
65 | } |
66 | } |
67 | |
68 | impl AsRawFd for Fd<'_> { |
69 | fn as_raw_fd(&self) -> RawFd { |
70 | self.as_fd().as_raw_fd() |
71 | } |
72 | } |
73 | |
74 | impl AsFd for Fd<'_> { |
75 | fn as_fd(&self) -> BorrowedFd<'_> { |
76 | match self { |
77 | Self::Borrowed(fd: &BorrowedFd<'_>) => fd.as_fd(), |
78 | Self::Owned(fd: &OwnedFd) => fd.as_fd(), |
79 | } |
80 | } |
81 | } |
82 | |
83 | impl<'fd, T> From<&'fd T> for Fd<'fd> |
84 | where |
85 | T: AsFd, |
86 | { |
87 | fn from(t: &'fd T) -> Self { |
88 | Self::Borrowed(t.as_fd()) |
89 | } |
90 | } |
91 | |
92 | impl 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 | |
98 | macro_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 | |
119 | fd_impl!(Fd<'_>); |
120 | |
121 | impl 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 | |
130 | impl<'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 = i32::deserialize(deserializer)?; |
136 | // SAFETY: The `'de` lifetimes will ensure the borrow won't outlive the raw FD. |
137 | let fd: BorrowedFd<'_> = unsafe { BorrowedFd::borrow_raw(fd:raw) }; |
138 | |
139 | Ok(Fd::Borrowed(fd)) |
140 | } |
141 | } |
142 | |
143 | impl PartialEq for Fd<'_> { |
144 | fn eq(&self, other: &Self) -> bool { |
145 | self.as_raw_fd().eq(&other.as_raw_fd()) |
146 | } |
147 | } |
148 | impl Eq for Fd<'_> {} |
149 | |
150 | impl PartialOrd for Fd<'_> { |
151 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
152 | Some(self.cmp(other)) |
153 | } |
154 | } |
155 | |
156 | impl 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 | |
162 | impl 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)] |
172 | pub struct OwnedFd { |
173 | inner: Fd<'static>, |
174 | } |
175 | |
176 | fd_impl!(OwnedFd); |
177 | |
178 | impl 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 | |
187 | impl<'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<'_> = 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 | |
203 | impl AsFd for OwnedFd { |
204 | fn as_fd(&self) -> BorrowedFd<'_> { |
205 | self.inner.as_fd() |
206 | } |
207 | } |
208 | |
209 | impl AsRawFd for OwnedFd { |
210 | fn as_raw_fd(&self) -> RawFd { |
211 | self.inner.as_raw_fd() |
212 | } |
213 | } |
214 | |
215 | impl From<fd::OwnedFd> for OwnedFd { |
216 | fn from(value: fd::OwnedFd) -> Self { |
217 | Self { |
218 | inner: Fd::Owned(value), |
219 | } |
220 | } |
221 | } |
222 | |
223 | impl From<OwnedFd> for fd::OwnedFd { |
224 | fn from(value: OwnedFd) -> fd::OwnedFd { |
225 | match value.inner { |
226 | Fd::Owned(fd: OwnedFd) => fd, |
227 | Fd::Borrowed(_) => unreachable!(), |
228 | } |
229 | } |
230 | } |
231 | |
232 | impl From<Fd<'static>> for OwnedFd { |
233 | fn from(value: Fd<'static>) -> Self { |
234 | Self { inner: value } |
235 | } |
236 | } |
237 | |
238 | impl std::fmt::Display for OwnedFd { |
239 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
240 | self.inner.fmt(f) |
241 | } |
242 | } |
243 | |