1#![cfg_attr(
9 feature = "serde-structural",
10 doc = r"
11Because bincode has various limitations in the structures that can
12be serialized, the [`Structural`] wrapper is available which forces
13structural serialization (currently uses msgpack). This requires the
14`serde-structural` feature.
15"
16)]
17use std::cell::RefCell;
18use std::io;
19use std::mem;
20use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
21use std::sync::Mutex;
22
23use serde_::{de, ser};
24use serde_::{de::DeserializeOwned, Deserialize, Serialize};
25
26thread_local! {
27 static IPC_FDS: RefCell<Vec<Vec<RawFd>>> = const {RefCell::new(Vec::new())};
28}
29
30pub struct Handle<F>(Mutex<Option<F>>);
42
43pub struct HandleRef(pub RawFd);
48
49impl<F: FromRawFd + IntoRawFd> Handle<F> {
50 pub fn new(f: F) -> Self {
52 f.into()
53 }
54
55 fn extract_raw_fd(&self) -> RawFd {
56 self.0
57 .lock()
58 .unwrap()
59 .take()
60 .map(|x| x.into_raw_fd())
61 .expect("cannot serialize handle twice")
62 }
63
64 pub fn into_inner(self) -> F {
66 self.0.lock().unwrap().take().expect("handle was moved")
67 }
68}
69
70impl<F: FromRawFd + IntoRawFd> From<F> for Handle<F> {
71 fn from(f: F) -> Self {
72 Handle(Mutex::new(Some(f)))
73 }
74}
75
76impl Serialize for HandleRef {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where
79 S: ser::Serializer,
80 {
81 if is_ipc_mode() {
82 let fd = self.0;
83 let idx = register_fd(fd);
84 idx.serialize(serializer)
85 } else {
86 Err(ser::Error::custom("can only serialize in ipc mode"))
87 }
88 }
89}
90
91impl<F: FromRawFd + IntoRawFd> Serialize for Handle<F> {
92 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93 where
94 S: ser::Serializer,
95 {
96 HandleRef(self.extract_raw_fd()).serialize(serializer)
97 }
98}
99
100impl<'de, F: FromRawFd + IntoRawFd> Deserialize<'de> for Handle<F> {
101 fn deserialize<D>(deserializer: D) -> Result<Handle<F>, D::Error>
102 where
103 D: de::Deserializer<'de>,
104 {
105 if is_ipc_mode() {
106 let idx = u32::deserialize(deserializer)?;
107 let fd = lookup_fd(idx).ok_or_else(|| de::Error::custom("fd not found in mapping"))?;
108 unsafe { Ok(Handle(Mutex::new(Some(FromRawFd::from_raw_fd(fd))))) }
109 } else {
110 Err(de::Error::custom("can only deserialize in ipc mode"))
111 }
112 }
113}
114
115struct ResetIpcSerde;
116
117impl Drop for ResetIpcSerde {
118 fn drop(&mut self) {
119 IPC_FDS.with(|x| x.borrow_mut().pop());
120 }
121}
122
123fn enter_ipc_mode<F: FnOnce() -> R, R>(f: F, fds: &mut Vec<RawFd>) -> R {
124 IPC_FDS.with(|x| x.borrow_mut().push(fds.clone()));
125 let reset = ResetIpcSerde;
126 let rv = f();
127 *fds = IPC_FDS.with(|x| x.borrow_mut().pop()).unwrap_or_default();
128 mem::forget(reset);
129 rv
130}
131
132fn register_fd(fd: RawFd) -> u32 {
133 IPC_FDS.with(|x| {
134 let mut x = x.borrow_mut();
135 let fds = x.last_mut().unwrap();
136 let rv = fds.len() as u32;
137 fds.push(fd);
138 rv
139 })
140}
141
142fn lookup_fd(idx: u32) -> Option<RawFd> {
143 IPC_FDS.with(|x| x.borrow().last().and_then(|l| l.get(idx as usize).copied()))
144}
145
146pub fn is_ipc_mode() -> bool {
151 IPC_FDS.with(|x| !x.borrow().is_empty())
152}
153
154#[allow(clippy::boxed_local)]
155fn bincode_to_io_error(err: bincode::Error) -> io::Error {
156 match *err {
157 bincode::ErrorKind::Io(err) => err,
158 err => io::Error::new(io::ErrorKind::InvalidData, err.to_string()),
159 }
160}
161
162pub fn serialize<S: Serialize>(s: S) -> io::Result<(Vec<u8>, Vec<RawFd>)> {
168 let mut fds = Vec::new();
169 let mut out = Vec::new();
170 enter_ipc_mode(|| bincode::serialize_into(&mut out, &s), &mut fds)
171 .map_err(bincode_to_io_error)?;
172 Ok((out, fds))
173}
174
175pub fn deserialize<D: DeserializeOwned>(bytes: &[u8], fds: &[RawFd]) -> io::Result<D> {
180 let mut fds = fds.to_owned();
181 let result =
182 enter_ipc_mode(|| bincode::deserialize(bytes), &mut fds).map_err(bincode_to_io_error)?;
183 Ok(result)
184}
185
186macro_rules! implement_handle_serialization {
187 ($ty:ty) => {
188 impl $crate::_serde_ref::Serialize for $ty {
189 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
190 where
191 S: $crate::_serde_ref::ser::Serializer,
192 {
193 $crate::_serde_ref::Serialize::serialize(
194 &$crate::serde::HandleRef(self.extract_raw_fd()),
195 serializer,
196 )
197 }
198 }
199 impl<'de> Deserialize<'de> for $ty {
200 fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
201 where
202 D: $crate::_serde_ref::de::Deserializer<'de>,
203 {
204 let handle: $crate::serde::Handle<$ty> =
205 $crate::_serde_ref::Deserialize::deserialize(deserializer)?;
206 Ok(handle.into_inner())
207 }
208 }
209 };
210}
211
212implement_handle_serialization!(crate::RawSender);
213implement_handle_serialization!(crate::RawReceiver);
214
215macro_rules! implement_typed_handle_serialization {
216 ($ty:ty) => {
217 impl<T: Serialize + DeserializeOwned> $crate::_serde_ref::Serialize for $ty {
218 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: $crate::_serde_ref::ser::Serializer,
221 {
222 $crate::_serde_ref::Serialize::serialize(
223 &$crate::serde::HandleRef(self.extract_raw_fd()),
224 serializer,
225 )
226 }
227 }
228 impl<'de, T: Serialize + DeserializeOwned> Deserialize<'de> for $ty {
229 fn deserialize<D>(deserializer: D) -> Result<$ty, D::Error>
230 where
231 D: $crate::_serde_ref::de::Deserializer<'de>,
232 {
233 let handle: $crate::serde::Handle<$ty> =
234 $crate::_serde_ref::Deserialize::deserialize(deserializer)?;
235 Ok(handle.into_inner())
236 }
237 }
238 };
239}
240
241implement_typed_handle_serialization!(crate::Sender<T>);
242implement_typed_handle_serialization!(crate::Receiver<T>);
243
244#[cfg(feature = "serde-structural")]
245mod structural {
246 use super::*;
247
248 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
264 pub struct Structural<T>(pub T);
265
266 impl<T: Serialize> Serialize for Structural<T> {
267 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
268 where
269 S: ser::Serializer,
270 {
271 let msgpack =
272 rmp_serde::to_vec(&self.0).map_err(|e| ser::Error::custom(e.to_string()))?;
273 serializer.serialize_bytes(&msgpack)
274 }
275 }
276
277 impl<'de, T: DeserializeOwned> Deserialize<'de> for Structural<T> {
278 fn deserialize<D>(deserializer: D) -> Result<Structural<T>, D::Error>
279 where
280 D: de::Deserializer<'de>,
281 {
282 let msgpack = Vec::<u8>::deserialize(deserializer)
283 .map_err(|e| de::Error::custom(e.to_string()))?;
284 Ok(Structural(
285 rmp_serde::from_slice(&msgpack).map_err(|e| de::Error::custom(e.to_string()))?,
286 ))
287 }
288 }
289}
290
291#[cfg(feature = "serde-structural")]
292pub use self::structural::*;
293
294#[test]
295fn test_basic() {
296 use std::io::Read;
297 let f = std::fs::File::open("src/serde.rs").unwrap();
298 let handle = Handle::from(f);
299 let (bytes, fds) = serialize(handle).unwrap();
300 let f2: Handle<std::fs::File> = deserialize(&bytes, &fds).unwrap();
301 let mut out = Vec::new();
302 f2.into_inner().read_to_end(&mut out).unwrap();
303 assert!(out.len() > 100);
304}
305
306#[test]
307#[cfg(feature = "serde-structural")]
308fn test_structural() {
309 #[derive(Serialize, Deserialize, Debug, PartialEq)]
310 #[serde(crate = "serde_")]
311 struct InnerStruct {
312 value: u64,
313 }
314
315 #[derive(Serialize, Deserialize, Debug, PartialEq)]
316 #[serde(crate = "serde_")]
317 struct BadStruct {
318 #[serde(flatten)]
319 inner: InnerStruct,
320 }
321
322 let (bytes, fds) = serialize(Structural(BadStruct {
323 inner: InnerStruct { value: 42 },
324 }))
325 .unwrap();
326 let value: Structural<BadStruct> = deserialize(&bytes, &fds).unwrap();
327 assert_eq!(
328 value.0,
329 BadStruct {
330 inner: InnerStruct { value: 42 },
331 }
332 );
333}