| 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 | |