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    pub fn new(value: T) -> Self {
24        Self(value)
25    }
26
27    pub fn unwrap(self) -> T {
28        self.0
29    }
30}
31
32impl<T> std::ops::Deref for Sendable<T> {
33    type Target = T;
34    fn deref(&self) -> &T {
35        &self.0
36    }
37}
38
39impl<T> AsRef<T> for Sendable<T> {
40    fn as_ref(&self) -> &T {
41        &self.0
42    }
43}
44
45impl<T> AsMut<T> for Sendable<T> {
46    fn as_mut(&mut self) -> &mut T {
47        &mut self.0
48    }
49}
50
51impl<T> From<T> for Sendable<T> {
52    fn from(t: T) -> Self {
53        Sendable(t)
54    }
55}
56
57impl<T> Display for Sendable<T>
58where
59    T: Display,
60{
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        write!(f, "{}", self.0)
63    }
64}
65
66impl<T> From<Sendable<T>> for JsValue
67where
68    T: Into<JsValue>,
69{
70    fn from(s: Sendable<T>) -> Self {
71        s.0.into()
72    }
73}
74
75#[derive(Debug)]
76pub struct SendableFuture<T>(pub T);
77unsafe impl<T> Send for SendableFuture<T> {}
78unsafe impl<T> Sync for SendableFuture<T> {}