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}