1use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
2use std::os::fd::{self, AsFd, AsRawFd, BorrowedFd, RawFd};
3
4use crate::{Basic, Type};
5
6#[derive(Debug)]
27pub enum Fd<'f> {
28 Borrowed(BorrowedFd<'f>),
29 Owned(fd::OwnedFd),
30}
31
32impl Fd<'_> {
33 pub fn try_to_owned(&self) -> crate::Result<Fd<'static>> {
35 self.as_fd()
36 .try_clone_to_owned()
37 .map(Fd::Owned)
38 .map_err(Into::into)
39 }
40
41 pub fn try_clone(&self) -> crate::Result<Self> {
43 Ok(match self {
44 Self::Borrowed(fd) => Self::Borrowed(*fd),
45 Self::Owned(fd) => Self::Owned(fd.try_clone()?),
46 })
47 }
48}
49
50impl<'f> From<BorrowedFd<'f>> for Fd<'f> {
51 fn from(fd: BorrowedFd<'f>) -> Self {
52 Self::Borrowed(fd)
53 }
54}
55
56impl From<fd::OwnedFd> for Fd<'_> {
57 fn from(fd: fd::OwnedFd) -> Self {
58 Self::Owned(fd)
59 }
60}
61
62impl From<OwnedFd> for Fd<'_> {
63 fn from(owned: OwnedFd) -> Self {
64 owned.inner
65 }
66}
67
68impl TryFrom<Fd<'_>> for fd::OwnedFd {
69 type Error = crate::Error;
70
71 fn try_from(fd: Fd<'_>) -> crate::Result<Self> {
72 match fd {
73 Fd::Borrowed(fd) => fd.try_clone_to_owned().map_err(Into::into),
74 Fd::Owned(fd) => Ok(fd),
75 }
76 }
77}
78
79impl AsRawFd for Fd<'_> {
80 fn as_raw_fd(&self) -> RawFd {
81 self.as_fd().as_raw_fd()
82 }
83}
84
85impl AsFd for Fd<'_> {
86 fn as_fd(&self) -> BorrowedFd<'_> {
87 match self {
88 Self::Borrowed(fd) => fd.as_fd(),
89 Self::Owned(fd) => fd.as_fd(),
90 }
91 }
92}
93
94impl<'fd, T> From<&'fd T> for Fd<'fd>
95where
96 T: AsFd,
97{
98 fn from(t: &'fd T) -> Self {
99 Self::Borrowed(t.as_fd())
100 }
101}
102
103impl std::fmt::Display for Fd<'_> {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 self.as_raw_fd().fmt(f)
106 }
107}
108
109macro_rules! fd_impl {
110 ($i:ty) => {
111 impl Basic for $i {
112 const SIGNATURE_CHAR: char = 'h';
113 const SIGNATURE_STR: &'static str = "h";
114 }
115
116 impl Type for $i {
117 const SIGNATURE: &'static crate::Signature = &crate::Signature::Fd;
118 }
119 };
120}
121
122fd_impl!(Fd<'_>);
123
124impl Serialize for Fd<'_> {
125 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126 where
127 S: Serializer,
128 {
129 serializer.serialize_i32(self.as_raw_fd())
130 }
131}
132
133impl<'de> Deserialize<'de> for Fd<'de> {
134 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
135 where
136 D: Deserializer<'de>,
137 {
138 let raw = i32::deserialize(deserializer)?;
139 debug_assert!(raw >= 0);
140 let fd = unsafe { BorrowedFd::borrow_raw(raw) };
142
143 Ok(Fd::Borrowed(fd))
144 }
145}
146
147impl PartialEq for Fd<'_> {
148 fn eq(&self, other: &Self) -> bool {
149 self.as_raw_fd().eq(&other.as_raw_fd())
150 }
151}
152impl Eq for Fd<'_> {}
153
154impl PartialOrd for Fd<'_> {
155 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
156 Some(self.cmp(other))
157 }
158}
159
160impl Ord for Fd<'_> {
161 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
162 self.as_raw_fd().cmp(&other.as_raw_fd())
163 }
164}
165
166impl std::hash::Hash for Fd<'_> {
167 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
168 self.as_raw_fd().hash(state)
169 }
170}
171
172#[derive(Debug, PartialEq, Eq, Hash)]
176pub struct OwnedFd {
177 inner: Fd<'static>,
178}
179
180fd_impl!(OwnedFd);
181
182impl Serialize for OwnedFd {
183 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184 where
185 S: Serializer,
186 {
187 self.inner.serialize(serializer)
188 }
189}
190
191impl<'de> Deserialize<'de> for OwnedFd {
192 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
193 where
194 D: Deserializer<'de>,
195 {
196 let fd = Fd::deserialize(deserializer)?;
197 Ok(OwnedFd {
198 inner: fd
199 .as_fd()
200 .try_clone_to_owned()
201 .map(Fd::Owned)
202 .map_err(D::Error::custom)?,
203 })
204 }
205}
206
207impl AsFd for OwnedFd {
208 fn as_fd(&self) -> BorrowedFd<'_> {
209 self.inner.as_fd()
210 }
211}
212
213impl AsRawFd for OwnedFd {
214 fn as_raw_fd(&self) -> RawFd {
215 self.inner.as_raw_fd()
216 }
217}
218
219impl From<fd::OwnedFd> for OwnedFd {
220 fn from(value: fd::OwnedFd) -> Self {
221 Self {
222 inner: Fd::Owned(value),
223 }
224 }
225}
226
227impl From<OwnedFd> for fd::OwnedFd {
228 fn from(value: OwnedFd) -> fd::OwnedFd {
229 match value.inner {
230 Fd::Owned(fd) => fd,
231 Fd::Borrowed(_) => unreachable!(),
232 }
233 }
234}
235
236impl From<Fd<'static>> for OwnedFd {
237 fn from(value: Fd<'static>) -> Self {
238 Self { inner: value }
239 }
240}
241
242impl std::fmt::Display for OwnedFd {
243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
244 self.inner.fmt(f)
245 }
246}