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