crossmist/
delayed.rs

1//! A wrapper for objects that require global state to be configured before deserialization.
2//!
3//! Typically, arguments passed to a cross-process entry function are deserialized shortly after the
4//! child process is started and just before the function is executed. This works for most types,
5//! but some objects, e.g. [`tokio::fs::File`], cannot be created before a specific action is
6//! performed (in this example, before the tokio runtime is started). This crate attempts to handle
7//! tokio gracefully, however there might be more cases when intervention is required.
8//!
9//! In these cases, the following pattern may be used:
10//!
11//! ```rust
12//! use crossmist::{Delayed, func, main, Object};
13//!
14//! #[derive(Object)]
15//! struct ComplexType;
16//!
17//! #[main]
18//! fn main() {
19//!     go.run(Delayed::new(ComplexType)).unwrap();
20//! }
21//!
22//! #[func]
23//! fn go(argument: Delayed<ComplexType>) {
24//!     // TODO: Initialize runtime here
25//!     let argument = argument.deserialize();
26//!     // Keep going...
27//! }
28//! ```
29
30use crate::{handles::OwnedHandle, Deserializer, NonTrivialObject, Object, Serializer};
31use std::fmt;
32use std::io::Result;
33
34/// A wrapper for objects that require global state to be configured before deserialization.
35pub struct Delayed<T: Object> {
36    inner: DelayedInner<T>,
37}
38
39// Use a private enum to stop the user from matching/creating it manually
40enum DelayedInner<T: Object> {
41    Serialized(Vec<u8>, Vec<OwnedHandle>),
42    Deserialized(T),
43}
44
45impl<T: Object> Delayed<T> {
46    /// Wrap an object. Use this in the parent process.
47    pub fn new(value: T) -> Self {
48        Self {
49            inner: DelayedInner::Deserialized(value),
50        }
51    }
52
53    /// Unwrap an object. Use this in the child process after initialization.
54    pub fn deserialize(self) -> Result<T> {
55        match self.inner {
56            DelayedInner::Serialized(data, handles) => unsafe {
57                Deserializer::new(data, handles).deserialize()
58            },
59            DelayedInner::Deserialized(_) => {
60                panic!("Cannot deserialize a deserialized Delayed value")
61            }
62        }
63    }
64}
65
66impl<T: Object> fmt::Debug for Delayed<T> {
67    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
68        fmt.debug_struct("Delayed").finish()
69    }
70}
71
72unsafe impl<T: Object> NonTrivialObject for Delayed<T> {
73    fn serialize_self_non_trivial(&self, s: &mut Serializer) {
74        match self.inner {
75            DelayedInner::Serialized(_, _) => panic!("Cannot serialize a serialized Delayed value"),
76            DelayedInner::Deserialized(ref value) => {
77                let mut s1 = Serializer::new();
78                s1.serialize(value);
79                let handles = s1
80                    .drain_handles()
81                    .into_iter()
82                    .map(|handle| s.add_handle(handle))
83                    .collect::<Vec<usize>>();
84                s.serialize(&handles);
85                s.serialize(&s1.into_vec());
86            }
87        }
88    }
89    unsafe fn deserialize_self_non_trivial(d: &mut Deserializer) -> Result<Self> {
90        let handles = d
91            .deserialize::<Vec<usize>>()?
92            .into_iter()
93            .map(|handle| d.drain_handle(handle))
94            .collect();
95        Ok(Delayed {
96            inner: DelayedInner::Serialized(d.deserialize()?, handles),
97        })
98    }
99}