1 | use core::borrow::Borrow; |
2 | use core::ops::{Deref, DerefMut}; |
3 | |
4 | use crate::describe::*; |
5 | use 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. |
17 | pub 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. |
37 | pub 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. |
63 | pub 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. |
102 | pub 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. |
120 | pub 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. |
138 | pub 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. |
156 | pub 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. |
179 | pub unsafe trait WasmPrimitive: Default {} |
180 | |
181 | unsafe impl WasmPrimitive for u32 {} |
182 | unsafe impl WasmPrimitive for i32 {} |
183 | unsafe impl WasmPrimitive for u64 {} |
184 | unsafe impl WasmPrimitive for i64 {} |
185 | unsafe impl WasmPrimitive for f32 {} |
186 | unsafe impl WasmPrimitive for f64 {} |
187 | unsafe 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. |
211 | pub 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. |
237 | pub 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 | |
246 | impl<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 | |
255 | use alloc::boxed::Box; |
256 | use 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. |
266 | pub 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. |
280 | pub 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)] |
302 | pub struct WasmRet<T: WasmAbi> { |
303 | prim1: T::Prim1, |
304 | prim2: T::Prim2, |
305 | prim3: T::Prim3, |
306 | prim4: T::Prim4, |
307 | } |
308 | |
309 | impl<T: WasmAbi> From<T> for WasmRet<T> { |
310 | fn from(value: T) -> Self { |
311 | let (prim1: ::Prim1, prim2: ::Prim2, prim3: ::Prim3, prim4: ::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. |
323 | impl<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. |
343 | pub 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 | } |
350 | |