Skip to main content

wasm_bindgen/convert/
traits.rs

1use core::borrow::Borrow;
2use core::ops::{Deref, DerefMut};
3use core::panic::AssertUnwindSafe;
4
5use crate::describe::*;
6use crate::sys::JsOption;
7use crate::{ErasableGeneric, JsValue};
8
9/// A trait for anything that can be converted into a type that can cross the
10/// Wasm ABI directly, eg `u32` or `f64`.
11///
12/// This is the opposite operation as `FromWasmAbi` and `Ref[Mut]FromWasmAbi`.
13///
14/// # ⚠️ Unstable
15///
16/// This is part of the internal [`convert`](crate::convert) module, **no
17/// stability guarantees** are provided. Use at your own risk. See its
18/// documentation for more details.
19pub trait IntoWasmAbi: WasmDescribe {
20    /// The Wasm ABI type that this converts into when crossing the ABI
21    /// boundary.
22    type Abi: WasmAbi;
23
24    /// Convert `self` into `Self::Abi` so that it can be sent across the wasm
25    /// ABI boundary.
26    fn into_abi(self) -> Self::Abi;
27}
28
29/// A trait for anything that can be recovered by-value from the Wasm ABI
30/// boundary, eg a Rust `u8` can be recovered from the Wasm ABI `u32` type.
31///
32/// This is the by-value variant of the opposite operation as `IntoWasmAbi`.
33///
34/// # ⚠️ Unstable
35///
36/// This is part of the internal [`convert`](crate::convert) module, **no
37/// stability guarantees** are provided. Use at your own risk. See its
38/// documentation for more details.
39pub trait FromWasmAbi: WasmDescribe {
40    /// The Wasm ABI type that this converts from when coming back out from the
41    /// ABI boundary.
42    type Abi: WasmAbi;
43
44    /// Recover a `Self` from `Self::Abi`.
45    ///
46    /// # Safety
47    ///
48    /// This is only safe to call when -- and implementations may assume that --
49    /// the supplied `Self::Abi` was previously generated by a call to `<Self as
50    /// IntoWasmAbi>::into_abi()` or the moral equivalent in JS.
51    unsafe fn from_abi(js: Self::Abi) -> Self;
52}
53
54/// A trait for anything that can be recovered as some sort of shared reference
55/// from the Wasm ABI boundary.
56///
57/// This is the shared reference variant of the opposite operation as
58/// `IntoWasmAbi`.
59///
60/// # ⚠️ Unstable
61///
62/// This is part of the internal [`convert`](crate::convert) module, **no
63/// stability guarantees** are provided. Use at your own risk. See its
64/// documentation for more details.
65pub trait RefFromWasmAbi: WasmDescribe {
66    /// The Wasm ABI type references to `Self` are recovered from.
67    type Abi: WasmAbi;
68
69    /// The type that holds the reference to `Self` for the duration of the
70    /// invocation of the function that has an `&Self` parameter. This is
71    /// required to ensure that the lifetimes don't persist beyond one function
72    /// call, and so that they remain anonymous.
73    type Anchor: Deref<Target = Self>;
74
75    /// Recover a `Self::Anchor` from `Self::Abi`.
76    ///
77    /// # Safety
78    ///
79    /// Same as `FromWasmAbi::from_abi`.
80    unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor;
81}
82
83/// A version of the `RefFromWasmAbi` trait with the additional requirement
84/// that the reference must remain valid as long as the anchor isn't dropped.
85///
86/// This isn't the case for `JsValue`'s `RefFromWasmAbi` implementation. To
87/// avoid having to allocate a spot for the `JsValue` on the `JsValue` heap,
88/// the `JsValue` is instead pushed onto the `JsValue` stack, and popped off
89/// again after the function that the reference was passed to returns. So,
90/// `JsValue` has a different `LongRefFromWasmAbi` implementation that behaves
91/// the same as `FromWasmAbi`, putting the value on the heap.
92///
93/// This is needed for async functions, where the reference needs to be valid
94/// for the whole length of the `Future`, rather than the initial synchronous
95/// call.
96///
97/// 'long ref' is short for 'long-lived reference'.
98///
99/// # ⚠️ Unstable
100///
101/// This is part of the internal [`convert`](crate::convert) module, **no
102/// stability guarantees** are provided. Use at your own risk. See its
103/// documentation for more details.
104pub trait LongRefFromWasmAbi: WasmDescribe {
105    /// Same as `RefFromWasmAbi::Abi`
106    type Abi: WasmAbi;
107
108    /// Same as `RefFromWasmAbi::Anchor`
109    type Anchor: Borrow<Self>;
110
111    /// Same as `RefFromWasmAbi::ref_from_abi`
112    unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor;
113}
114
115/// Dual of the `RefFromWasmAbi` trait, except for mutable references.
116///
117/// # ⚠️ Unstable
118///
119/// This is part of the internal [`convert`](crate::convert) module, **no
120/// stability guarantees** are provided. Use at your own risk. See its
121/// documentation for more details.
122pub trait RefMutFromWasmAbi: WasmDescribe {
123    /// Same as `RefFromWasmAbi::Abi`
124    type Abi: WasmAbi;
125    /// Same as `RefFromWasmAbi::Anchor`
126    type Anchor: DerefMut<Target = Self>;
127    /// Same as `RefFromWasmAbi::ref_from_abi`
128    unsafe fn ref_mut_from_abi(js: Self::Abi) -> Self::Anchor;
129}
130
131/// Indicates that this type can be passed to JS as `Option<Self>`.
132///
133/// This trait is used when implementing `IntoWasmAbi for Option<T>`.
134///
135/// # ⚠️ Unstable
136///
137/// This is part of the internal [`convert`](crate::convert) module, **no
138/// stability guarantees** are provided. Use at your own risk. See its
139/// documentation for more details.
140pub trait OptionIntoWasmAbi: IntoWasmAbi {
141    /// Returns an ABI instance indicating "none", which JS will interpret as
142    /// the `None` branch of this option.
143    ///
144    /// It should be guaranteed that the `IntoWasmAbi` can never produce the ABI
145    /// value returned here.
146    fn none() -> Self::Abi;
147}
148
149/// Indicates that this type can be received from JS as `Option<Self>`.
150///
151/// This trait is used when implementing `FromWasmAbi for Option<T>`.
152///
153/// # ⚠️ Unstable
154///
155/// This is part of the internal [`convert`](crate::convert) module, **no
156/// stability guarantees** are provided. Use at your own risk. See its
157/// documentation for more details.
158pub trait OptionFromWasmAbi: FromWasmAbi {
159    /// Tests whether the argument is a "none" instance. If so it will be
160    /// deserialized as `None`, and otherwise it will be passed to
161    /// `FromWasmAbi`.
162    fn is_none(abi: &Self::Abi) -> bool;
163}
164
165/// A trait for any type which maps to a Wasm primitive type when used in FFI
166/// (`i32`, `i64`, `f32`, or `f64`).
167///
168/// This is with the exception of `()` (and other zero-sized types), which are
169/// also allowed because they're ignored: no arguments actually get added.
170///
171/// # Safety
172///
173/// This is an unsafe trait to implement as there's no guarantee the type
174/// actually maps to a primitive type.
175///
176/// # ⚠️ Unstable
177///
178/// This is part of the internal [`convert`](crate::convert) module, **no
179/// stability guarantees** are provided. Use at your own risk. See its
180/// documentation for more details.
181pub unsafe trait WasmPrimitive: Default {}
182
183unsafe impl WasmPrimitive for u32 {}
184unsafe impl WasmPrimitive for i32 {}
185unsafe impl WasmPrimitive for u64 {}
186unsafe impl WasmPrimitive for i64 {}
187unsafe impl WasmPrimitive for f32 {}
188unsafe impl WasmPrimitive for f64 {}
189unsafe impl WasmPrimitive for () {}
190
191/// A trait which represents types that can be passed across the Wasm ABI
192/// boundary, by being split into multiple Wasm primitive types.
193///
194/// Up to 4 primitives are supported; if you don't want to use all of them, you
195/// can set the rest to `()`, which will cause them to be ignored.
196///
197/// You need to be careful how many primitives you use, however:
198/// `Result<T, JsValue>` uses up 2 primitives to store the error, and so it
199/// doesn't work if `T` uses more than 2 primitives.
200///
201/// So, if you're adding support for a type that needs 3 or more primitives and
202/// is able to be returned, you have to add another primitive here.
203///
204/// There's already one type that uses 3 primitives: `&mut [T]`. However, it
205/// can't be returned anyway, so it doesn't matter that
206/// `Result<&mut [T], JsValue>` wouldn't work.
207///
208/// # ⚠️ Unstable
209///
210/// This is part of the internal [`convert`](crate::convert) module, **no
211/// stability guarantees** are provided. Use at your own risk. See its
212/// documentation for more details.
213pub trait WasmAbi {
214    type Prim1: WasmPrimitive;
215    type Prim2: WasmPrimitive;
216    type Prim3: WasmPrimitive;
217    type Prim4: WasmPrimitive;
218
219    /// Splits this type up into primitives to be sent over the ABI.
220    fn split(self) -> (Self::Prim1, Self::Prim2, Self::Prim3, Self::Prim4);
221    /// Reconstructs this type from primitives received over the ABI.
222    fn join(prim1: Self::Prim1, prim2: Self::Prim2, prim3: Self::Prim3, prim4: Self::Prim4)
223        -> Self;
224}
225
226/// A trait representing how to interpret the return value of a function for
227/// the Wasm ABI.
228///
229/// This is very similar to the `IntoWasmAbi` trait and in fact has a blanket
230/// implementation for all implementors of the `IntoWasmAbi`. The primary use
231/// case of this trait is to enable functions to return `Result`, interpreting
232/// an error as "rethrow this to JS"
233///
234/// # ⚠️ Unstable
235///
236/// This is part of the internal [`convert`](crate::convert) module, **no
237/// stability guarantees** are provided. Use at your own risk. See its
238/// documentation for more details.
239pub trait ReturnWasmAbi: WasmDescribe {
240    /// Same as `IntoWasmAbi::Abi`
241    type Abi: WasmAbi;
242
243    /// Same as `IntoWasmAbi::into_abi`, except that it may throw and never
244    /// return in the case of `Err`.
245    fn return_abi(self) -> Self::Abi;
246}
247
248impl<T: IntoWasmAbi> ReturnWasmAbi for T {
249    type Abi = T::Abi;
250
251    #[inline]
252    fn return_abi(self) -> Self::Abi {
253        self.into_abi()
254    }
255}
256
257use alloc::boxed::Box;
258use core::marker::Sized;
259
260/// Trait for element types to implement IntoWasmAbi for vectors of
261/// themselves.
262///
263/// # ⚠️ Unstable
264///
265/// This is part of the internal [`convert`](crate::convert) module, **no
266/// stability guarantees** are provided. Use at your own risk. See its
267/// documentation for more details.
268pub trait VectorIntoWasmAbi: WasmDescribeVector + Sized {
269    type Abi: WasmAbi;
270
271    fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi;
272}
273
274/// Trait for element types to implement FromWasmAbi for vectors of
275/// themselves.
276///
277/// # ⚠️ Unstable
278///
279/// This is part of the internal [`convert`](crate::convert) module, **no
280/// stability guarantees** are provided. Use at your own risk. See its
281/// documentation for more details.
282pub trait VectorFromWasmAbi: WasmDescribeVector + Sized {
283    type Abi: WasmAbi;
284
285    unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]>;
286}
287
288/// A repr(C) struct containing all of the primitives of a `WasmAbi` type, in
289/// order.
290///
291/// This is used as the return type of imported/exported functions. `WasmAbi`
292/// types aren't guaranteed to be FFI-safe, so we can't return them directly:
293/// instead we return this.
294///
295/// If all but one of the primitives is `()`, this corresponds to returning the
296/// remaining primitive directly, otherwise a return pointer is used.
297///
298/// # ⚠️ Unstable
299///
300/// This is part of the internal [`convert`](crate::convert) module, **no
301/// stability guarantees** are provided. Use at your own risk. See its
302/// documentation for more details.
303#[repr(C)]
304pub struct WasmRet<T: WasmAbi> {
305    prim1: T::Prim1,
306    prim2: T::Prim2,
307    prim3: T::Prim3,
308    prim4: T::Prim4,
309}
310
311impl<T: WasmAbi> From<T> for WasmRet<T> {
312    fn from(value: T) -> Self {
313        let (prim1, prim2, prim3, prim4) = value.split();
314        Self {
315            prim1,
316            prim2,
317            prim3,
318            prim4,
319        }
320    }
321}
322
323// Ideally this'd just be an `Into<T>` implementation, but unfortunately that
324// doesn't work because of the orphan rule.
325impl<T: WasmAbi> WasmRet<T> {
326    /// Joins the components of this `WasmRet` back into the type they represent.
327    pub fn join(self) -> T {
328        T::join(self.prim1, self.prim2, self.prim3, self.prim4)
329    }
330}
331
332/// [`TryFromJsValue`] is a trait for converting a JavaScript value ([`JsValue`])
333/// into a Rust type. It is used by the [`wasm_bindgen`](wasm_bindgen_macro::wasm_bindgen)
334/// proc-macro to allow conversion to user types.
335///
336/// The semantics of this trait for various types are designed to provide a runtime
337/// analog of the static semantics implemented by the IntoWasmAbi function bindgen,
338/// with the exception that conversions are constrained to not cast invalid types.
339///
340/// For example, where the Wasm static semantics will permit `foo(x: i32)` when passed
341/// from JS `foo("5")` to treat that as `foo(5)`, this trait will instead throw. Apart
342/// from these reduced type conversion cases, behaviours should otherwise match the
343/// static semantics.
344///
345/// Types implementing this trait must specify their conversion logic from
346/// [`JsValue`] to the Rust type, handling any potential errors that may occur
347/// during the conversion process.
348///
349/// # ⚠️ Unstable
350///
351/// This is part of the internal [`convert`](crate::convert) module, **no
352/// stability guarantees** are provided. Use at your own risk. See its
353/// documentation for more details.
354pub trait TryFromJsValue: Sized {
355    /// Performs the conversion.
356    fn try_from_js_value(value: JsValue) -> Result<Self, JsValue> {
357        Self::try_from_js_value_ref(&value).ok_or(value)
358    }
359
360    /// Performs the conversion.
361    fn try_from_js_value_ref(value: &JsValue) -> Option<Self>;
362}
363
364impl<T: FromWasmAbi> FromWasmAbi for AssertUnwindSafe<T> {
365    type Abi = T::Abi;
366
367    unsafe fn from_abi(js: Self::Abi) -> Self {
368        AssertUnwindSafe(T::from_abi(js))
369    }
370}
371
372/// A trait for defining upcast relationships from a source type.
373///
374/// This is the inverse of [`Upcast<T>`] - instead of implementing
375/// `impl Upcast<Target> for Source`, you implement `impl UpcastFrom<Source> for Target`.
376///
377/// # Why UpcastFrom?
378///
379/// This resolves Rust's orphan rule issues: you can implement `UpcastFrom<MyType>`
380/// for external types when `MyType` is local to your crate, whereas implementing
381/// `Upcast<ExternalType>` would be prohibited by orphan rules.
382///
383/// # ⚠️ Unstable
384///
385/// This is part of the internal [`convert`](crate::convert) module, **no
386/// stability guarantees** are provided. Use at your own risk. See its
387/// documentation for more details.
388///
389/// # Relationship to Upcast
390///
391/// `UpcastFrom<S>` provides a blanket implementation of `Upcast<T>`:
392/// ```ignore
393/// impl<S, T> Upcast<T> for S where T: UpcastFrom<S> {}
394/// ```
395///
396/// This means implementing `UpcastFrom<Source> for Target` automatically gives you
397/// `Upcast<Target> for Source`, enabling `source.upcast()` to produce `Target`.
398pub trait UpcastFrom<S: ?Sized> {}
399
400/// A trait for type-safe generic upcasting.
401///
402/// # ⚠️ Unstable
403///
404/// This is part of the internal [`convert`](crate::convert) module, **no
405/// stability guarantees** are provided. Use at your own risk. See its
406/// documentation for more details.
407///
408/// # Note
409///
410/// `Upcast<T>` has a blanket implementation for all types where `T: UpcastFrom<Self>`.
411/// New upcast relationships should typically be defined by implementing `FromUpcast`
412/// rather than `Upcast` directly, to avoid orphan rule issues.
413pub trait Upcast<T: ?Sized> {
414    /// Perform a zero-cost type-safe upcast to a wider ref type within the Wasm
415    /// bindgen generics type system.
416    ///
417    /// This enables proper nested conversions that obey subtyping rules,
418    /// supporting strict API type checking.
419    ///
420    /// The common pattern when passing a narrow type is to call `upcast()`
421    /// or `upcast_into()` to obtain the correct type for the function usage,
422    /// while ensuring safe type checked usage.
423    ///
424    /// For example, if passing `Promise<Number>` as an argument to a function
425    /// where `Promise<JsValue>` is expected, or `Function<JsValue>` as an
426    /// argument where `Function<Number>` is expected.
427    ///
428    /// This is a compile time conversion only by the nature of the erasable
429    /// generics type system.
430    #[inline]
431    fn upcast(&self) -> &T
432    where
433        Self: ErasableGeneric,
434        T: Sized + ErasableGeneric<Repr = <Self as ErasableGeneric>::Repr>,
435    {
436        unsafe { &*(self as *const Self as *const T) }
437    }
438
439    /// Perform a zero-cost type-safe upcast to a wider type within the Wasm
440    /// bindgen generics type system.
441    ///
442    /// This enables proper nested conversions that obey subtyping rules,
443    /// supporting strict API type checking.
444    ///
445    /// The common pattern when passing a narrow type is to call `upcast()`
446    /// or `upcast_into()` to obtain the correct type for the function usage,
447    /// while ensuring safe type checked usage.
448    ///
449    /// For example, if passing `Promise<Number>` as an argument to a function
450    /// where `Promise<JsValue>` is expected, or `FunctionArgs<JsValue>` as an
451    /// argument where `FunctionArgs<Number>` is expected.
452    ///
453    /// This is a compile time conversion only by the nature of the erasable
454    /// generics type system.
455    #[inline]
456    fn upcast_into(self) -> T
457    where
458        Self: Sized + ErasableGeneric,
459        T: Sized + ErasableGeneric<Repr = <Self as ErasableGeneric>::Repr>,
460    {
461        unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(self)) }
462    }
463}
464
465// Blanket impl: UpcastFrom<S> for T implies Upcast<T> for S
466impl<S, T> Upcast<T> for S
467where
468    T: UpcastFrom<S> + ?Sized,
469    S: ?Sized,
470{
471}
472
473// Reference impls using UpcastFrom
474impl<'a, T, Target> UpcastFrom<&'a mut T> for &'a mut Target where Target: UpcastFrom<T> {}
475impl<'a, T, Target> UpcastFrom<&'a T> for &'a Target where Target: UpcastFrom<T> {}
476
477// Tuple upcasts with structural covariance
478macro_rules! impl_tuple_upcast {
479    ([$($T:ident)+] [$($Target:ident)+]) => {
480        // Structural covariance: (T...) -> (Target...)
481        impl<$($T,)+ $($Target,)+> UpcastFrom<($($T,)+)> for ($($Target,)+)
482        where
483            $($Target: JsGeneric + UpcastFrom<$T>,)+
484            $($T: JsGeneric,)+
485        {
486        }
487        impl<$($T: JsGeneric,)+ $($Target: JsGeneric,)+> UpcastFrom<($($T,)+)> for JsOption<($($Target,)+)>
488        where
489            $($Target: JsGeneric + UpcastFrom<$T>,)+
490            $($T: JsGeneric,)+
491        {
492        }
493    };
494}
495impl_tuple_upcast!([T1][Target1]);
496impl_tuple_upcast!([T1 T2] [Target1 Target2]);
497impl_tuple_upcast!([T1 T2 T3] [Target1 Target2 Target3]);
498impl_tuple_upcast!([T1 T2 T3 T4] [Target1 Target2 Target3 Target4]);
499impl_tuple_upcast!([T1 T2 T3 T4 T5] [Target1 Target2 Target3 Target4 Target5]);
500impl_tuple_upcast!([T1 T2 T3 T4 T5 T6] [Target1 Target2 Target3 Target4 Target5 Target6]);
501impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7] [Target1 Target2 Target3 Target4 Target5 Target6 Target7]);
502impl_tuple_upcast!([T1 T2 T3 T4 T5 T6 T7 T8] [Target1 Target2 Target3 Target4 Target5 Target6 Target7 Target8]);
503
504/// A convenience trait for types that erase to [`JsValue`].
505///
506/// This is a shorthand for `ErasableGeneric<Repr = JsValue>`, used as a bound
507/// on generic parameters that must be representable as JavaScript values.
508///
509/// # When to Use
510///
511/// Use `JsGeneric` as a trait bound when you need a generic type that:
512/// - Can be passed to/from JavaScript
513/// - Is type-erased to `JsValue` at the FFI boundary
514///
515/// # Examples
516///
517/// ```ignore
518/// use wasm_bindgen::JsGeneric;
519///
520/// fn process_js_values<T: JsGeneric>(items: &[T]) {
521///     // T can be any JS-compatible type
522/// }
523/// ```
524///
525/// # Implementors
526///
527/// This trait is automatically implemented for all types that implement
528/// `ErasableGeneric<Repr = JsValue>`, including:
529/// - All `js_sys` types (`Object`, `Array`, `Function`, etc.)
530/// - `JsValue` itself
531/// - Custom types imported via `#[wasm_bindgen]`
532pub trait JsGeneric:
533    ErasableGeneric<Repr = JsValue> + UpcastFrom<Self> + Upcast<Self> + Upcast<JsValue> + 'static
534{
535}
536
537impl<T: ErasableGeneric<Repr = JsValue> + UpcastFrom<T> + Upcast<JsValue> + 'static> JsGeneric
538    for T
539{
540}