1 | use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; |
2 | use static_assertions::assert_impl_all; |
3 | use std::os::unix::io; |
4 | |
5 | use crate::{Basic, EncodingFormat, Signature, Type}; |
6 | |
7 | /// A [`RawFd`](https://doc.rust-lang.org/std/os/unix/io/type.RawFd.html) wrapper. |
8 | /// |
9 | /// See also `OwnedFd` if you need a wrapper that takes ownership of the file. |
10 | /// |
11 | /// We wrap the `RawFd` type so that we can implement [`Serialize`] and [`Deserialize`] for it. |
12 | /// File descriptors are serialized in a special way and you need to use specific [serializer] and |
13 | /// [deserializer] API when file descriptors are or could be involved. |
14 | /// |
15 | /// [`Serialize`]: https://docs.serde.rs/serde/trait.Serialize.html |
16 | /// [`Deserialize`]: https://docs.serde.rs/serde/de/trait.Deserialize.html |
17 | /// [deserializer]: fn.from_slice_fds.html |
18 | /// [serializer]: fn.to_bytes_fds.html |
19 | #[derive (Debug, PartialEq, Eq, Hash, Clone, Copy)] |
20 | pub struct Fd(io::RawFd); |
21 | |
22 | macro_rules! fd_impl { |
23 | ($i:ident) => { |
24 | assert_impl_all!($i: Send, Sync, Unpin); |
25 | |
26 | impl Basic for $i { |
27 | const SIGNATURE_CHAR: char = 'h' ; |
28 | const SIGNATURE_STR: &'static str = "h" ; |
29 | |
30 | fn alignment(format: EncodingFormat) -> usize { |
31 | u32::alignment(format) |
32 | } |
33 | } |
34 | |
35 | impl Type for $i { |
36 | fn signature() -> Signature<'static> { |
37 | Signature::from_static_str_unchecked(Self::SIGNATURE_STR) |
38 | } |
39 | } |
40 | }; |
41 | } |
42 | |
43 | fd_impl!(Fd); |
44 | |
45 | impl Serialize for Fd { |
46 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
47 | where |
48 | S: Serializer, |
49 | { |
50 | serializer.serialize_i32(self.0) |
51 | } |
52 | } |
53 | |
54 | impl<'de> Deserialize<'de> for Fd { |
55 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
56 | where |
57 | D: Deserializer<'de>, |
58 | { |
59 | Ok(Fd(i32::deserialize(deserializer)?)) |
60 | } |
61 | } |
62 | |
63 | impl From<io::RawFd> for Fd { |
64 | fn from(value: io::RawFd) -> Self { |
65 | Self(value) |
66 | } |
67 | } |
68 | |
69 | impl<T> From<&T> for Fd |
70 | where |
71 | T: io::AsRawFd, |
72 | { |
73 | fn from(t: &T) -> Self { |
74 | Self(t.as_raw_fd()) |
75 | } |
76 | } |
77 | |
78 | impl io::AsRawFd for Fd { |
79 | fn as_raw_fd(&self) -> io::RawFd { |
80 | self.0 |
81 | } |
82 | } |
83 | |
84 | impl std::fmt::Display for Fd { |
85 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
86 | self.0.fmt(f) |
87 | } |
88 | } |
89 | |
90 | /// An owned [`RawFd`](https://doc.rust-lang.org/std/os/unix/io/type.RawFd.html) wrapper. |
91 | /// |
92 | /// See also [`Fd`]. This type owns the file and will close it on drop. On deserialize, it will |
93 | /// duplicate the file descriptor. |
94 | #[derive (Debug, PartialEq, Eq, Hash)] |
95 | pub struct OwnedFd { |
96 | inner: io::RawFd, |
97 | } |
98 | |
99 | impl Drop for OwnedFd { |
100 | fn drop(&mut self) { |
101 | unsafe { |
102 | libc::close(self.inner); |
103 | } |
104 | } |
105 | } |
106 | |
107 | fd_impl!(OwnedFd); |
108 | |
109 | impl Serialize for OwnedFd { |
110 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
111 | where |
112 | S: Serializer, |
113 | { |
114 | serializer.serialize_i32(self.inner) |
115 | } |
116 | } |
117 | |
118 | impl<'de> Deserialize<'de> for OwnedFd { |
119 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
120 | where |
121 | D: Deserializer<'de>, |
122 | { |
123 | let fd: i32 = unsafe { libc::dup(fd:i32::deserialize(deserializer)?) }; |
124 | if fd < 0 { |
125 | return Err(D::Error::custom(msg:std::io::Error::last_os_error())); |
126 | } |
127 | Ok(OwnedFd { inner: fd }) |
128 | } |
129 | } |
130 | |
131 | impl io::FromRawFd for OwnedFd { |
132 | unsafe fn from_raw_fd(fd: io::RawFd) -> Self { |
133 | Self { inner: fd } |
134 | } |
135 | } |
136 | |
137 | impl io::AsRawFd for OwnedFd { |
138 | fn as_raw_fd(&self) -> io::RawFd { |
139 | self.inner |
140 | } |
141 | } |
142 | |
143 | impl io::IntoRawFd for OwnedFd { |
144 | fn into_raw_fd(self) -> io::RawFd { |
145 | let fd: i32 = self.inner; |
146 | std::mem::forget(self); |
147 | fd |
148 | } |
149 | } |
150 | |
151 | impl std::fmt::Display for OwnedFd { |
152 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
153 | self.inner.fmt(f) |
154 | } |
155 | } |
156 | |