wasm_bindgen/convert/
traits.rs

1use core::borrow::Borrow;
2use core::ops::{Deref, DerefMut};
3use core::panic::AssertUnwindSafe;
4
5use crate::describe::*;
6use crate::JsValue;
7
8/// A trait for anything that can be converted into a type that can cross the
9/// Wasm ABI directly, eg `u32` or `f64`.
10///
11/// This is the opposite operation as `FromWasmAbi` and `Ref[Mut]FromWasmAbi`.
12///
13/// # ⚠️ Unstable
14///
15/// This is part of the internal [`convert`](crate::convert) module, **no
16/// stability guarantees** are provided. Use at your own risk. See its
17/// documentation for more details.
18pub trait IntoWasmAbi: WasmDescribe {
19    /// The Wasm ABI type that this converts into when crossing the ABI
20    /// boundary.
21    type Abi: WasmAbi;
22
23    /// Convert `self` into `Self::Abi` so that it can be sent across the wasm
24    /// ABI boundary.
25    fn into_abi(self) -> Self::Abi;
26}
27
28/// A trait for anything that can be recovered by-value from the Wasm ABI
29/// boundary, eg a Rust `u8` can be recovered from the Wasm ABI `u32` type.
30///
31/// This is the by-value variant of the opposite operation as `IntoWasmAbi`.
32///
33/// # ⚠️ Unstable
34///
35/// This is part of the internal [`convert`](crate::convert) module, **no
36/// stability guarantees** are provided. Use at your own risk. See its
37/// documentation for more details.
38pub trait FromWasmAbi: WasmDescribe {
39    /// The Wasm ABI type that this converts from when coming back out from the
40    /// ABI boundary.
41    type Abi: WasmAbi;
42
43    /// Recover a `Self` from `Self::Abi`.
44    ///
45    /// # Safety
46    ///
47    /// This is only safe to call when -- and implementations may assume that --
48    /// the supplied `Self::Abi` was previously generated by a call to `<Self as
49    /// IntoWasmAbi>::into_abi()` or the moral equivalent in JS.
50    unsafe fn from_abi(js: Self::Abi) -> Self;
51}
52
53/// A trait for anything that can be recovered as some sort of shared reference
54/// from the Wasm ABI boundary.
55///
56/// This is the shared reference variant of the opposite operation as
57/// `IntoWasmAbi`.
58///
59/// # ⚠️ Unstable
60///
61/// This is part of the internal [`convert`](crate::convert) module, **no
62/// stability guarantees** are provided. Use at your own risk. See its
63/// documentation for more details.
64pub trait RefFromWasmAbi: WasmDescribe {
65    /// The Wasm ABI type references to `Self` are recovered from.
66    type Abi: WasmAbi;
67
68    /// The type that holds the reference to `Self` for the duration of the
69    /// invocation of the function that has an `&Self` parameter. This is
70    /// required to ensure that the lifetimes don't persist beyond one function
71    /// call, and so that they remain anonymous.
72    type Anchor: Deref<Target = Self>;
73
74    /// Recover a `Self::Anchor` from `Self::Abi`.
75    ///
76    /// # Safety
77    ///
78    /// Same as `FromWasmAbi::from_abi`.
79    unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor;
80}
81
82/// A version of the `RefFromWasmAbi` trait with the additional requirement
83/// that the reference must remain valid as long as the anchor isn't dropped.
84///
85/// This isn't the case for `JsValue`'s `RefFromWasmAbi` implementation. To
86/// avoid having to allocate a spot for the `JsValue` on the `JsValue` heap,
87/// the `JsValue` is instead pushed onto the `JsValue` stack, and popped off
88/// again after the function that the reference was passed to returns. So,
89/// `JsValue` has a different `LongRefFromWasmAbi` implementation that behaves
90/// the same as `FromWasmAbi`, putting the value on the heap.
91///
92/// This is needed for async functions, where the reference needs to be valid
93/// for the whole length of the `Future`, rather than the initial synchronous
94/// call.
95///
96/// 'long ref' is short for 'long-lived reference'.
97///
98/// # ⚠️ Unstable
99///
100/// This is part of the internal [`convert`](crate::convert) module, **no
101/// stability guarantees** are provided. Use at your own risk. See its
102/// documentation for more details.
103pub trait LongRefFromWasmAbi: WasmDescribe {
104    /// Same as `RefFromWasmAbi::Abi`
105    type Abi: WasmAbi;
106
107    /// Same as `RefFromWasmAbi::Anchor`
108    type Anchor: Borrow<Self>;
109
110    /// Same as `RefFromWasmAbi::ref_from_abi`
111    unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor;
112}
113
114/// Dual of the `RefFromWasmAbi` trait, except for mutable references.
115///
116/// # ⚠️ Unstable
117///
118/// This is part of the internal [`convert`](crate::convert) module, **no
119/// stability guarantees** are provided. Use at your own risk. See its
120/// documentation for more details.
121pub trait RefMutFromWasmAbi: WasmDescribe {
122    /// Same as `RefFromWasmAbi::Abi`
123    type Abi: WasmAbi;
124    /// Same as `RefFromWasmAbi::Anchor`
125    type Anchor: DerefMut<Target = Self>;
126    /// Same as `RefFromWasmAbi::ref_from_abi`
127    unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor;
128}
129
130/// Indicates that this type can be passed to JS as `Option<Self>`.
131///
132/// This trait is used when implementing `IntoWasmAbi for Option<T>`.
133///
134/// # ⚠️ Unstable
135///
136/// This is part of the internal [`convert`](crate::convert) module, **no
137/// stability guarantees** are provided. Use at your own risk. See its
138/// documentation for more details.
139pub trait OptionIntoWasmAbi: IntoWasmAbi {
140    /// Returns an ABI instance indicating "none", which JS will interpret as
141    /// the `None` branch of this option.
142    ///
143    /// It should be guaranteed that the `IntoWasmAbi` can never produce the ABI
144    /// value returned here.
145    fn none() -> Self::Abi;
146}
147
148/// Indicates that this type can be received from JS as `Option<Self>`.
149///
150/// This trait is used when implementing `FromWasmAbi for Option<T>`.
151///
152/// # ⚠️ Unstable
153///
154/// This is part of the internal [`convert`](crate::convert) module, **no
155/// stability guarantees** are provided. Use at your own risk. See its
156/// documentation for more details.
157pub trait OptionFromWasmAbi: FromWasmAbi {
158    /// Tests whether the argument is a "none" instance. If so it will be
159    /// deserialized as `None`, and otherwise it will be passed to
160    /// `FromWasmAbi`.
161    fn is_none(abi: &Self::Abi) -> bool;
162}
163
164/// A trait for any type which maps to a Wasm primitive type when used in FFI
165/// (`i32`, `i64`, `f32`, or `f64`).
166///
167/// This is with the exception of `()` (and other zero-sized types), which are
168/// also allowed because they're ignored: no arguments actually get added.
169///
170/// # Safety
171///
172/// This is an unsafe trait to implement as there's no guarantee the type
173/// actually maps to a primitive type.
174///
175/// # ⚠️ Unstable
176///
177/// This is part of the internal [`convert`](crate::convert) module, **no
178/// stability guarantees** are provided. Use at your own risk. See its
179/// documentation for more details.
180pub unsafe trait WasmPrimitive: Default {}
181
182unsafe impl WasmPrimitive for u32 {}
183unsafe impl WasmPrimitive for i32 {}
184unsafe impl WasmPrimitive for u64 {}
185unsafe impl WasmPrimitive for i64 {}
186unsafe impl WasmPrimitive for f32 {}
187unsafe impl WasmPrimitive for f64 {}
188unsafe impl WasmPrimitive for () {}
189
190/// A trait which represents types that can be passed across the Wasm ABI
191/// boundary, by being split into multiple Wasm primitive types.
192///
193/// Up to 4 primitives are supported; if you don't want to use all of them, you
194/// can set the rest to `()`, which will cause them to be ignored.
195///
196/// You need to be careful how many primitives you use, however:
197/// `Result<T, JsValue>` uses up 2 primitives to store the error, and so it
198/// doesn't work if `T` uses more than 2 primitives.
199///
200/// So, if you're adding support for a type that needs 3 or more primitives and
201/// is able to be returned, you have to add another primitive here.
202///
203/// There's already one type that uses 3 primitives: `&mut [T]`. However, it
204/// can't be returned anyway, so it doesn't matter that
205/// `Result<&mut [T], JsValue>` wouldn't work.
206///
207/// # ⚠️ Unstable
208///
209/// This is part of the internal [`convert`](crate::convert) module, **no
210/// stability guarantees** are provided. Use at your own risk. See its
211/// documentation for more details.
212pub trait WasmAbi {
213    type Prim1: WasmPrimitive;
214    type Prim2: WasmPrimitive;
215    type Prim3: WasmPrimitive;
216    type Prim4: WasmPrimitive;
217
218    /// Splits this type up into primitives to be sent over the ABI.
219    fn split(self) -> (Self::Prim1, Self::Prim2, Self::Prim3, Self::Prim4);
220    /// Reconstructs this type from primitives received over the ABI.
221    fn join(prim1: Self::Prim1, prim2: Self::Prim2, prim3: Self::Prim3, prim4: Self::Prim4)
222        -> Self;
223}
224
225/// A trait representing how to interpret the return value of a function for
226/// the Wasm ABI.
227///
228/// This is very similar to the `IntoWasmAbi` trait and in fact has a blanket
229/// implementation for all implementors of the `IntoWasmAbi`. The primary use
230/// case of this trait is to enable functions to return `Result`, interpreting
231/// an error as "rethrow this to JS"
232///
233/// # ⚠️ Unstable
234///
235/// This is part of the internal [`convert`](crate::convert) module, **no
236/// stability guarantees** are provided. Use at your own risk. See its
237/// documentation for more details.
238pub trait ReturnWasmAbi: WasmDescribe {
239    /// Same as `IntoWasmAbi::Abi`
240    type Abi: WasmAbi;
241
242    /// Same as `IntoWasmAbi::into_abi`, except that it may throw and never
243    /// return in the case of `Err`.
244    fn return_abi(self) -> Self::Abi;
245}
246
247impl<T: IntoWasmAbi> ReturnWasmAbi for T {
248    type Abi = T::Abi;
249
250    #[inline]
251    fn return_abi(self) -> Self::Abi {
252        self.into_abi()
253    }
254}
255
256use alloc::boxed::Box;
257use core::marker::Sized;
258
259/// Trait for element types to implement IntoWasmAbi for vectors of
260/// themselves.
261///
262/// # ⚠️ Unstable
263///
264/// This is part of the internal [`convert`](crate::convert) module, **no
265/// stability guarantees** are provided. Use at your own risk. See its
266/// documentation for more details.
267pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
268    type Abi: WasmAbi;
269
270    fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
271}
272
273/// Trait for element types to implement FromWasmAbi for vectors of
274/// themselves.
275///
276/// # ⚠️ Unstable
277///
278/// This is part of the internal [`convert`](crate::convert) module, **no
279/// stability guarantees** are provided. Use at your own risk. See its
280/// documentation for more details.
281pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
282    type Abi: WasmAbi;
283
284    unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
285}
286
287/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in
288/// order.
289///
290/// This is used as the return type of imported/exported functions. `WasmAbi`
291/// types aren't guaranteed to be FFI-safe, so we can't return them directly:
292/// instead we return this.
293///
294/// If all but one of the primitives is `()`, this corresponds to returning the
295/// remaining primitive directly, otherwise a return pointer is used.
296///
297/// # ⚠️ Unstable
298///
299/// This is part of the internal [`convert`](crate::convert) module, **no
300/// stability guarantees** are provided. Use at your own risk. See its
301/// documentation for more details.
302#[repr(C)]
303pub struct WasmRet<T: WasmAbi> {
304    prim1: T::Prim1,
305    prim2: T::Prim2,
306    prim3: T::Prim3,
307    prim4: T::Prim4,
308}
309
310impl<T: WasmAbi> From<T> for WasmRet<T> {
311    fn from(value: T) -> Self {
312        let (prim1, prim2, prim3, prim4) = value.split();
313        Self {
314            prim1,
315            prim2,
316            prim3,
317            prim4,
318        }
319    }
320}
321
322// Ideally this'd just be an `Into<T>` implementation, but unfortunately that
323// doesn't work because of the orphan rule.
324impl<T: WasmAbi> WasmRet<T> {
325    /// Joins the components of this `WasmRet` back into the type they represent.
326    pub fn join(self) -> T {
327        T::join(self.prim1, self.prim2, self.prim3, self.prim4)
328    }
329}
330
331/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
332/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
333/// proc-macro to allow conversion to user types.
334///
335/// The semantics of this trait for various types are designed to provide a runtime
336/// analog of the static semantics implemented by the IntoWasmAbi function bindgen,
337/// with the exception that conversions are constrained to not cast invalid types.
338///
339/// For example, where the Wasm static semantics will permit `foo(x: i32)` when passed
340/// from JS `foo("5")` to treat that as `foo(5)`, this trait will instead throw. Apart
341/// from these reduced type conversion cases, behaviours should otherwise match the
342/// static semantics.
343///
344/// Types implementing this trait must specify their conversion logic from
345/// [`JsValue`] to the Rust type, handling any potential errors that may occur
346/// during the conversion process.
347///
348/// # ⚠️ Unstable
349///
350/// This is part of the internal [`convert`](crate::convert) module, **no
351/// stability guarantees** are provided. Use at your own risk. See its
352/// documentation for more details.
353pub trait TryFromJsValue: Sized {
354    /// Performs the conversion.
355    fn try_from_js_value(value: JsValue) -> Result<Self, JsValue> {
356        Self::try_from_js_value_ref(&value).ok_or(value)
357    }
358
359    /// Performs the conversion.
360    fn try_from_js_value_ref(value: &JsValue) -> Option<Self>;
361}
362
363impl<T: FromWasmAbi> FromWasmAbi for AssertUnwindSafe<T> {
364    type Abi = T::Abi;
365
366    unsafe fn from_abi(js: Self::Abi) -> Self {
367        AssertUnwindSafe(T::from_abi(js))
368    }
369}