Skip to main content

workflow_core/
sendable.rs

1//!
2//! Sendable NewType for automatic Send marker wrapping of JS primitives.
3//!
4
5use std::fmt::Display;
6use wasm_bindgen::JsValue;
7
8///
9/// Sendable wrapper for JS primitives.
10///
11/// Wrapping any JS primitive (JsValue, JsString, JsArray, JsObject, etc.) in
12/// `Sendable<T>` wraps the value with the Send marker, making it transportable
13/// across "thread boundaries". In reality, this allows JS primitives to be
14/// used safely within a single-threaded WASM async environment (browser).
15///
16#[derive(Debug)]
17pub struct Sendable<T>(pub T);
18
19unsafe impl<T> Send for Sendable<T> {}
20unsafe impl<T> Sync for Sendable<T> {}
21
22impl<T> Sendable<T> {
23    /// Wraps `value` in a [`Sendable`], adding `Send`/`Sync` markers.
24    pub fn new(value: T) -> Self {
25        Self(value)
26    }
27
28    /// Consumes the wrapper and returns the inner value.
29    pub fn unwrap(self) -> T {
30        self.0
31    }
32}
33
34impl<T> std::ops::Deref for Sendable<T> {
35    type Target = T;
36    fn deref(&self) -> &T {
37        &self.0
38    }
39}
40
41impl<T> AsRef<T> for Sendable<T> {
42    fn as_ref(&self) -> &T {
43        &self.0
44    }
45}
46
47impl<T> AsMut<T> for Sendable<T> {
48    fn as_mut(&mut self) -> &mut T {
49        &mut self.0
50    }
51}
52
53impl<T> From<T> for Sendable<T> {
54    fn from(t: T) -> Self {
55        Sendable(t)
56    }
57}
58
59impl<T> Display for Sendable<T>
60where
61    T: Display,
62{
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(f, "{}", self.0)
65    }
66}
67
68impl<T> From<Sendable<T>> for JsValue
69where
70    T: Into<JsValue>,
71{
72    fn from(s: Sendable<T>) -> Self {
73        s.0.into()
74    }
75}
76
77/// Sendable wrapper for a future, adding `Send`/`Sync` markers so a non-`Send`
78/// future (e.g. one driving JS primitives) can be used across thread boundaries
79/// within a single-threaded WASM async environment.
80#[derive(Debug)]
81pub struct SendableFuture<T>(pub T);
82unsafe impl<T> Send for SendableFuture<T> {}
83unsafe impl<T> Sync for SendableFuture<T> {}