1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::char;
4use core::mem::{self, ManuallyDrop};
5use core::ptr::NonNull;
6
7use crate::__rt::marker::ErasableGeneric;
8use crate::__rt::{WasmSignedWordRepr, WasmWordRepr};
9use crate::convert::traits::{WasmAbi, WasmPrimitive};
10use crate::convert::{
11 FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, MaybeFromWasmAbi, MaybeIntoWasmAbi,
12 NullableFromWasmAbi, NullableIntoWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi, RefFromWasmAbi,
13 ReturnWasmAbi, TryFromJsValue, UpcastFrom,
14};
15use crate::sys::Promising;
16use crate::sys::{JsNullable, JsOption, Undefined};
17use crate::{throw_str, Clamped, JsError, JsValue, Nullable};
18
19impl<T: WasmPrimitive> WasmAbi for T {
21 type Prim1 = Self;
22 type Prim2 = ();
23 type Prim3 = ();
24 type Prim4 = ();
25
26 #[inline]
27 fn split(self) -> (Self, (), (), ()) {
28 (self, (), (), ())
29 }
30
31 #[inline]
32 fn join(prim: Self, _: (), _: (), _: ()) -> Self {
33 prim
34 }
35}
36
37impl WasmAbi for i128 {
38 type Prim1 = u64;
39 type Prim2 = u64;
40 type Prim3 = ();
41 type Prim4 = ();
42
43 #[inline]
44 fn split(self) -> (u64, u64, (), ()) {
45 let low = self as u64;
46 let high = (self >> 64) as u64;
47 (low, high, (), ())
48 }
49
50 #[inline]
51 fn join(low: u64, high: u64, _: (), _: ()) -> Self {
52 (((high as u128) << 64) | low as u128) as i128
53 }
54}
55impl WasmAbi for u128 {
56 type Prim1 = u64;
57 type Prim2 = u64;
58 type Prim3 = ();
59 type Prim4 = ();
60
61 #[inline]
62 fn split(self) -> (u64, u64, (), ()) {
63 let low = self as u64;
64 let high = (self >> 64) as u64;
65 (low, high, (), ())
66 }
67
68 #[inline]
69 fn join(low: u64, high: u64, _: (), _: ()) -> Self {
70 ((high as u128) << 64) | low as u128
71 }
72}
73
74#[doc(hidden)]
78#[derive(Clone, Copy)]
79pub struct MaybeAbi<T> {
80 pub tag: u32,
81 pub value: T,
82}
83
84impl<T: WasmAbi<Prim4 = ()>> WasmAbi for MaybeAbi<T> {
85 type Prim1 = u32;
86 type Prim2 = T::Prim1;
87 type Prim3 = T::Prim2;
88 type Prim4 = T::Prim3;
89
90 #[inline]
91 fn split(self) -> (u32, T::Prim1, T::Prim2, T::Prim3) {
92 let (prim1, prim2, prim3, ()) = self.value.split();
93 (self.tag, prim1, prim2, prim3)
94 }
95
96 #[inline]
97 fn join(tag: u32, prim1: T::Prim1, prim2: T::Prim2, prim3: T::Prim3) -> Self {
98 MaybeAbi {
99 tag,
100 value: T::join(prim1, prim2, prim3, ()),
101 }
102 }
103}
104
105macro_rules! type_wasm_native {
106 ($($t:tt as $c:tt)*) => ($(
107 impl IntoWasmAbi for $t {
108 type Abi = $c;
109
110 #[inline]
111 fn into_abi(self) -> $c { self as $c }
112 }
113
114 impl FromWasmAbi for $t {
115 type Abi = $c;
116
117 #[inline]
118 unsafe fn from_abi(js: $c) -> Self { js as $t }
119 }
120
121 impl MaybeIntoWasmAbi for $t {
122 type MaybeAbi = MaybeAbi<$c>;
123
124 #[inline]
125 fn into_maybe_abi(self) -> MaybeAbi<$c> {
126 MaybeAbi { tag: 1, value: self as $c }
127 }
128
129 #[inline]
130 fn none() -> MaybeAbi<$c> {
131 MaybeAbi { tag: 0, value: 0 as $c }
132 }
133 }
134
135 impl NullableIntoWasmAbi for $t {
136 #[inline]
137 fn null() -> MaybeAbi<$c> {
138 MaybeAbi { tag: 2, value: 0 as $c }
139 }
140 }
141
142 impl MaybeFromWasmAbi for $t {
143 type MaybeAbi = MaybeAbi<$c>;
144
145 #[inline]
146 unsafe fn from_maybe_abi(js: MaybeAbi<$c>) -> Self {
147 js.value as $t
148 }
149
150 #[inline]
151 fn is_none(js: &MaybeAbi<$c>) -> bool {
152 js.tag == 0
153 }
154 }
155
156 impl NullableFromWasmAbi for $t {
157 #[inline]
158 fn is_null(js: &MaybeAbi<$c>) -> bool {
159 js.tag == 2
160 }
161 }
162
163 impl UpcastFrom<$t> for JsValue {}
164 impl UpcastFrom<$t> for JsOption<JsValue> {}
165 impl UpcastFrom<$t> for JsNullable<JsValue> {}
166 impl UpcastFrom<$t> for $t {}
167 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Option<Target> {}
168 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Nullable<Target> {}
169 )*)
170}
171
172type_wasm_native!(
173 i64 as i64
174 u64 as u64
175 i128 as i128
176 u128 as u128
177 f64 as f64
178);
179
180impl UpcastFrom<u64> for u128 {}
181impl UpcastFrom<u64> for JsOption<u128> {}
182impl UpcastFrom<u64> for JsNullable<u128> {}
183impl UpcastFrom<i64> for i128 {}
184impl UpcastFrom<i64> for JsOption<i128> {}
185impl UpcastFrom<i64> for JsNullable<i128> {}
186
187const F64_ABI_OPTION_SENTINEL: f64 = 9007199254740991_f64;
197
198#[doc(hidden)]
202pub const F64_ABI_NULL_SENTINEL: f64 = 9007199254740990_f64;
203
204macro_rules! type_wasm_native_f64_option {
205 ($($t:tt as $c:tt)*) => ($(
206 impl IntoWasmAbi for $t {
207 type Abi = $c;
208
209 #[inline]
210 fn into_abi(self) -> $c { self as $c }
211 }
212
213 impl FromWasmAbi for $t {
214 type Abi = $c;
215
216 #[inline]
217 unsafe fn from_abi(js: $c) -> Self { js as $t }
218 }
219
220 unsafe impl ErasableGeneric for $t {
221 type Repr = $t;
222 }
223
224 impl Promising for $t {
225 type Resolution = $t;
226 }
227
228 impl MaybeIntoWasmAbi for $t {
229 type MaybeAbi = f64;
230
231 #[inline]
232 fn into_maybe_abi(self) -> f64 {
233 self as $c as f64
234 }
235
236 #[inline]
237 fn none() -> f64 {
238 F64_ABI_OPTION_SENTINEL
239 }
240 }
241
242 impl NullableIntoWasmAbi for $t {
243 #[inline]
244 fn null() -> f64 {
245 F64_ABI_NULL_SENTINEL
246 }
247 }
248
249 impl MaybeFromWasmAbi for $t {
250 type MaybeAbi = f64;
251
252 #[inline]
253 unsafe fn from_maybe_abi(js: f64) -> Self {
254 js as $c as $t
255 }
256
257 #[inline]
258 fn is_none(js: &f64) -> bool {
259 *js == F64_ABI_OPTION_SENTINEL
260 }
261 }
262
263 impl NullableFromWasmAbi for $t {
264 #[inline]
265 fn is_null(js: &f64) -> bool {
266 *js == F64_ABI_NULL_SENTINEL
267 }
268 }
269
270 impl UpcastFrom<$t> for JsValue {}
271 impl UpcastFrom<$t> for JsOption<JsValue> {}
272 impl UpcastFrom<$t> for JsNullable<JsValue> {}
273 impl UpcastFrom<$t> for $t {}
274 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Option<Target> {}
275 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Nullable<Target> {}
276 )*)
277}
278
279type_wasm_native_f64_option!(
280 i32 as i32
281 u32 as u32
282 f32 as f32
283 isize as WasmSignedWordRepr
284 usize as WasmWordRepr
285);
286
287#[cfg(target_pointer_width = "32")]
288impl UpcastFrom<isize> for i32 {}
289#[cfg(target_pointer_width = "32")]
290impl UpcastFrom<isize> for JsOption<i32> {}
291#[cfg(target_pointer_width = "32")]
292impl UpcastFrom<isize> for JsNullable<i32> {}
293
294impl UpcastFrom<isize> for i64 {}
295impl UpcastFrom<isize> for JsOption<i64> {}
296impl UpcastFrom<isize> for JsNullable<i64> {}
297impl UpcastFrom<isize> for i128 {}
298impl UpcastFrom<isize> for JsOption<i128> {}
299impl UpcastFrom<isize> for JsNullable<i128> {}
300
301impl UpcastFrom<i32> for isize {}
302impl UpcastFrom<i32> for JsOption<isize> {}
303impl UpcastFrom<i32> for JsNullable<isize> {}
304impl UpcastFrom<i32> for i64 {}
305impl UpcastFrom<i32> for JsOption<i64> {}
306impl UpcastFrom<i32> for JsNullable<i64> {}
307impl UpcastFrom<i32> for i128 {}
308impl UpcastFrom<i32> for JsOption<i128> {}
309impl UpcastFrom<i32> for JsNullable<i128> {}
310
311impl UpcastFrom<u32> for usize {}
312impl UpcastFrom<u32> for JsOption<usize> {}
313impl UpcastFrom<u32> for JsNullable<usize> {}
314impl UpcastFrom<u32> for u64 {}
315impl UpcastFrom<u32> for JsOption<u64> {}
316impl UpcastFrom<u32> for JsNullable<u64> {}
317impl UpcastFrom<u32> for u128 {}
318impl UpcastFrom<u32> for JsOption<u128> {}
319impl UpcastFrom<u32> for JsNullable<u128> {}
320
321#[cfg(target_pointer_width = "32")]
322impl UpcastFrom<usize> for u32 {}
323#[cfg(target_pointer_width = "32")]
324impl UpcastFrom<usize> for JsOption<u32> {}
325#[cfg(target_pointer_width = "32")]
326impl UpcastFrom<usize> for JsNullable<u32> {}
327impl UpcastFrom<usize> for u64 {}
328impl UpcastFrom<usize> for JsOption<u64> {}
329impl UpcastFrom<usize> for JsNullable<u64> {}
330impl UpcastFrom<usize> for u128 {}
331impl UpcastFrom<usize> for JsOption<u128> {}
332impl UpcastFrom<usize> for JsNullable<u128> {}
333
334impl UpcastFrom<f32> for f64 {}
335impl UpcastFrom<f32> for JsOption<f64> {}
336impl UpcastFrom<f32> for JsNullable<f64> {}
337
338const U32_ABI_OPTION_SENTINEL: u32 = 0x00FF_FFFFu32;
344
345const U32_ABI_NULL_SENTINEL: u32 = 0x00FF_FFFEu32;
347
348macro_rules! type_abi_as_u32 {
349 ($($t:tt)*) => ($(
350 impl IntoWasmAbi for $t {
351 type Abi = u32;
352
353 #[inline]
354 fn into_abi(self) -> u32 { self as u32 }
355 }
356
357 impl FromWasmAbi for $t {
358 type Abi = u32;
359
360 #[inline]
361 unsafe fn from_abi(js: u32) -> Self { js as $t }
362 }
363
364 impl OptionIntoWasmAbi for $t {
365 #[inline]
366 fn none() -> u32 { U32_ABI_OPTION_SENTINEL }
367 }
368
369 impl OptionFromWasmAbi for $t {
370 #[inline]
371 fn is_none(js: &u32) -> bool { *js == U32_ABI_OPTION_SENTINEL }
372 }
373
374 impl_nullable_into_shared_abi!(null = U32_ABI_NULL_SENTINEL; [] $t);
375 impl_nullable_from_shared_abi!(is_null = |js| *js == U32_ABI_NULL_SENTINEL; [] $t);
376
377 unsafe impl ErasableGeneric for $t {
378 type Repr = $t;
379 }
380
381 impl Promising for $t {
382 type Resolution = $t;
383 }
384
385 impl UpcastFrom<$t> for JsValue {}
386 impl UpcastFrom<$t> for JsOption<JsValue> {}
387 impl UpcastFrom<$t> for JsNullable<JsValue> {}
388 impl UpcastFrom<$t> for $t {}
389 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Option<Target> {}
390 impl<Target: UpcastFrom<$t>> UpcastFrom<$t> for Nullable<Target> {}
391 )*)
392}
393
394type_abi_as_u32!(i8 u8 i16 u16);
395
396impl UpcastFrom<i8> for i16 {}
397impl UpcastFrom<i8> for JsOption<i16> {}
398impl UpcastFrom<i8> for JsNullable<i16> {}
399impl UpcastFrom<i8> for i32 {}
400impl UpcastFrom<i8> for JsOption<i32> {}
401impl UpcastFrom<i8> for JsNullable<i32> {}
402impl UpcastFrom<i8> for i64 {}
403impl UpcastFrom<i8> for JsOption<i64> {}
404impl UpcastFrom<i8> for JsNullable<i64> {}
405impl UpcastFrom<i8> for i128 {}
406impl UpcastFrom<i8> for JsOption<i128> {}
407impl UpcastFrom<i8> for JsNullable<i128> {}
408
409impl UpcastFrom<u8> for u16 {}
410impl UpcastFrom<u8> for JsOption<u16> {}
411impl UpcastFrom<u8> for JsNullable<u16> {}
412impl UpcastFrom<u8> for u32 {}
413impl UpcastFrom<u8> for JsOption<u32> {}
414impl UpcastFrom<u8> for JsNullable<u32> {}
415impl UpcastFrom<u8> for u64 {}
416impl UpcastFrom<u8> for JsOption<u64> {}
417impl UpcastFrom<u8> for JsNullable<u64> {}
418impl UpcastFrom<u8> for u128 {}
419impl UpcastFrom<u8> for JsOption<u128> {}
420impl UpcastFrom<u8> for JsNullable<u128> {}
421
422impl UpcastFrom<i16> for i32 {}
423impl UpcastFrom<i16> for JsOption<i32> {}
424impl UpcastFrom<i16> for JsNullable<i32> {}
425impl UpcastFrom<i16> for i64 {}
426impl UpcastFrom<i16> for JsOption<i64> {}
427impl UpcastFrom<i16> for JsNullable<i64> {}
428impl UpcastFrom<i16> for i128 {}
429impl UpcastFrom<i16> for JsOption<i128> {}
430impl UpcastFrom<i16> for JsNullable<i128> {}
431
432impl UpcastFrom<u16> for u32 {}
433impl UpcastFrom<u16> for JsOption<u32> {}
434impl UpcastFrom<u16> for JsNullable<u32> {}
435impl UpcastFrom<u16> for u64 {}
436impl UpcastFrom<u16> for JsOption<u64> {}
437impl UpcastFrom<u16> for JsNullable<u64> {}
438impl UpcastFrom<u16> for u128 {}
439impl UpcastFrom<u16> for JsOption<u128> {}
440impl UpcastFrom<u16> for JsNullable<u128> {}
441
442impl IntoWasmAbi for bool {
443 type Abi = u32;
444
445 #[inline]
446 fn into_abi(self) -> u32 {
447 self as u32
448 }
449}
450
451impl FromWasmAbi for bool {
452 type Abi = u32;
453
454 #[inline]
455 unsafe fn from_abi(js: u32) -> bool {
456 js != 0
457 }
458}
459
460impl OptionIntoWasmAbi for bool {
461 #[inline]
462 fn none() -> u32 {
463 U32_ABI_OPTION_SENTINEL
464 }
465}
466
467impl OptionFromWasmAbi for bool {
468 #[inline]
469 fn is_none(js: &u32) -> bool {
470 *js == U32_ABI_OPTION_SENTINEL
471 }
472}
473
474impl_nullable_into_shared_abi!(null = U32_ABI_NULL_SENTINEL; [] bool);
475impl_nullable_from_shared_abi!(is_null = |js| *js == U32_ABI_NULL_SENTINEL; [] bool);
476
477unsafe impl ErasableGeneric for bool {
478 type Repr = bool;
479}
480
481impl Promising for bool {
482 type Resolution = bool;
483}
484
485impl UpcastFrom<bool> for JsValue {}
486impl UpcastFrom<bool> for JsOption<JsValue> {}
487impl UpcastFrom<bool> for JsNullable<JsValue> {}
488impl UpcastFrom<bool> for bool {}
489impl<Target: UpcastFrom<bool>> UpcastFrom<bool> for Option<Target> {}
490impl<Target: UpcastFrom<bool>> UpcastFrom<bool> for Nullable<Target> {}
491
492impl IntoWasmAbi for char {
493 type Abi = u32;
494
495 #[inline]
496 fn into_abi(self) -> u32 {
497 self as u32
498 }
499}
500
501impl FromWasmAbi for char {
502 type Abi = u32;
503
504 #[inline]
505 unsafe fn from_abi(js: u32) -> char {
506 char::from_u32_unchecked(js)
508 }
509}
510
511impl OptionIntoWasmAbi for char {
512 #[inline]
513 fn none() -> u32 {
514 U32_ABI_OPTION_SENTINEL
515 }
516}
517
518impl OptionFromWasmAbi for char {
519 #[inline]
520 fn is_none(js: &u32) -> bool {
521 *js == U32_ABI_OPTION_SENTINEL
522 }
523}
524
525impl_nullable_into_shared_abi!(null = U32_ABI_NULL_SENTINEL; [] char);
526impl_nullable_from_shared_abi!(is_null = |js| *js == U32_ABI_NULL_SENTINEL; [] char);
527
528unsafe impl ErasableGeneric for char {
529 type Repr = char;
530}
531
532impl Promising for char {
533 type Resolution = char;
534}
535
536impl UpcastFrom<char> for JsValue {}
537impl UpcastFrom<char> for JsOption<JsValue> {}
538impl UpcastFrom<char> for JsNullable<JsValue> {}
539impl UpcastFrom<char> for char {}
540impl<Target: UpcastFrom<char>> UpcastFrom<char> for Option<Target> {}
541impl<Target: UpcastFrom<char>> UpcastFrom<char> for Nullable<Target> {}
542
543impl<T> IntoWasmAbi for *const T {
544 type Abi = WasmWordRepr;
545
546 #[inline]
547 fn into_abi(self) -> Self::Abi {
548 self as usize as WasmWordRepr
549 }
550}
551
552impl<T> FromWasmAbi for *const T {
553 type Abi = WasmWordRepr;
554
555 #[inline]
556 unsafe fn from_abi(js: Self::Abi) -> *const T {
557 js as usize as *const T
558 }
559}
560
561unsafe impl<T: ErasableGeneric> ErasableGeneric for *const T {
562 type Repr = *const T::Repr;
563}
564
565impl<T, Target> UpcastFrom<*const T> for *const Target where Target: UpcastFrom<T> {}
566impl<T, Target> UpcastFrom<*const T> for JsOption<*const Target> where Target: UpcastFrom<T> {}
567impl<T, Target> UpcastFrom<*const T> for JsNullable<*const Target> where Target: UpcastFrom<T> {}
568
569unsafe impl<T: ErasableGeneric> ErasableGeneric for Option<T> {
570 type Repr = Option<<T as ErasableGeneric>::Repr>;
571}
572
573impl<T, Target> UpcastFrom<Option<T>> for Option<Target> where Target: UpcastFrom<T> {}
574impl<T, Target> UpcastFrom<Option<T>> for JsOption<Option<Target>> where Target: UpcastFrom<T> {}
575impl<T, Target> UpcastFrom<Option<T>> for JsNullable<Option<Target>> where Target: UpcastFrom<T> {}
576impl<T> UpcastFrom<Option<T>> for JsValue where JsValue: UpcastFrom<T> {}
579
580macro_rules! nullable_ptr_abi {
583 ($($t:ty),*) => ($(
584 impl<T> MaybeIntoWasmAbi for $t {
585 type MaybeAbi = f64;
586
587 #[inline]
588 fn into_maybe_abi(self) -> f64 {
589 self as usize as f64
590 }
591
592 #[inline]
593 fn none() -> f64 {
594 F64_ABI_OPTION_SENTINEL
595 }
596 }
597
598 impl<T> NullableIntoWasmAbi for $t {
599 #[inline]
600 fn null() -> f64 {
601 F64_ABI_NULL_SENTINEL
602 }
603 }
604
605 impl<T> MaybeFromWasmAbi for $t {
606 type MaybeAbi = f64;
607
608 #[inline]
609 unsafe fn from_maybe_abi(js: f64) -> Self {
610 js as usize as $t
611 }
612
613 #[inline]
614 fn is_none(js: &f64) -> bool {
615 *js == F64_ABI_OPTION_SENTINEL
616 }
617 }
618
619 impl<T> NullableFromWasmAbi for $t {
620 #[inline]
621 fn is_null(js: &f64) -> bool {
622 *js == F64_ABI_NULL_SENTINEL
623 }
624 }
625 )*)
626}
627
628nullable_ptr_abi!(*const T, *mut T);
629
630impl<T> IntoWasmAbi for *mut T {
631 type Abi = WasmWordRepr;
632
633 #[inline]
634 fn into_abi(self) -> Self::Abi {
635 self as usize as WasmWordRepr
636 }
637}
638
639impl<T> FromWasmAbi for *mut T {
640 type Abi = WasmWordRepr;
641
642 #[inline]
643 unsafe fn from_abi(js: Self::Abi) -> *mut T {
644 js as usize as *mut T
645 }
646}
647
648impl<T> IntoWasmAbi for NonNull<T> {
649 type Abi = WasmWordRepr;
650
651 #[inline]
652 fn into_abi(self) -> Self::Abi {
653 self.as_ptr() as usize as WasmWordRepr
654 }
655}
656
657impl<T> OptionIntoWasmAbi for NonNull<T> {
658 #[inline]
659 fn none() -> Self::Abi {
660 0 as WasmWordRepr
661 }
662}
663
664impl<T> FromWasmAbi for NonNull<T> {
665 type Abi = WasmWordRepr;
666
667 #[inline]
668 unsafe fn from_abi(js: Self::Abi) -> Self {
669 NonNull::new_unchecked(js as usize as *mut T)
671 }
672}
673
674impl<T> OptionFromWasmAbi for NonNull<T> {
675 #[inline]
676 fn is_none(js: &Self::Abi) -> bool {
677 *js == 0 as WasmWordRepr
678 }
679}
680
681impl IntoWasmAbi for JsValue {
682 type Abi = u32;
683
684 #[inline]
685 fn into_abi(self) -> u32 {
686 let ret = self.idx;
687 mem::forget(self);
688 ret
689 }
690}
691
692impl FromWasmAbi for JsValue {
693 type Abi = u32;
694
695 #[inline]
696 unsafe fn from_abi(js: u32) -> JsValue {
697 JsValue::_new(js)
698 }
699}
700
701impl IntoWasmAbi for &JsValue {
702 type Abi = u32;
703
704 #[inline]
705 fn into_abi(self) -> u32 {
706 self.idx
707 }
708}
709
710impl RefFromWasmAbi for JsValue {
711 type Abi = u32;
712 type Anchor = ManuallyDrop<JsValue>;
713
714 #[inline]
715 unsafe fn ref_from_abi(js: u32) -> Self::Anchor {
716 ManuallyDrop::new(JsValue::_new(js))
717 }
718}
719
720impl LongRefFromWasmAbi for JsValue {
721 type Abi = u32;
722 type Anchor = JsValue;
723
724 #[inline]
725 unsafe fn long_ref_from_abi(js: u32) -> Self::Anchor {
726 Self::from_abi(js)
727 }
728}
729
730impl OptionIntoWasmAbi for JsValue {
731 #[inline]
732 fn none() -> u32 {
733 crate::__rt::JSIDX_UNDEFINED
734 }
735}
736
737impl OptionIntoWasmAbi for &JsValue {
738 #[inline]
739 fn none() -> u32 {
740 crate::__rt::JSIDX_UNDEFINED
741 }
742}
743
744impl OptionFromWasmAbi for JsValue {
745 #[inline]
746 fn is_none(js: &u32) -> bool {
747 unsafe { Self::ref_from_abi(*js) }.is_undefined()
748 }
749}
750
751impl_nullable_into_shared_abi!(null = crate::__rt::JSIDX_NULL; [] JsValue);
752impl_nullable_into_shared_abi!(null = crate::__rt::JSIDX_NULL; [] &JsValue);
753impl_nullable_from_shared_abi!(is_null = |js| *js == crate::__rt::JSIDX_NULL; [] JsValue);
757
758impl<T: OptionIntoWasmAbi> MaybeIntoWasmAbi for T {
762 type MaybeAbi = T::Abi;
763
764 #[inline]
765 fn into_maybe_abi(self) -> T::Abi {
766 self.into_abi()
767 }
768
769 #[inline]
770 fn none() -> T::Abi {
771 <T as OptionIntoWasmAbi>::none()
772 }
773}
774
775impl<T: OptionFromWasmAbi> MaybeFromWasmAbi for T {
776 type MaybeAbi = T::Abi;
777
778 #[inline]
779 unsafe fn from_maybe_abi(js: T::Abi) -> Self {
780 T::from_abi(js)
781 }
782
783 #[inline]
784 unsafe fn try_from_maybe_abi(js: T::Abi) -> Result<Self, &'static str> {
785 T::try_from_abi(js)
786 }
787
788 #[inline]
789 fn is_none(js: &T::Abi) -> bool {
790 <T as OptionFromWasmAbi>::is_none(js)
791 }
792}
793
794impl<T: MaybeIntoWasmAbi> IntoWasmAbi for Option<T> {
795 type Abi = T::MaybeAbi;
796
797 #[inline]
798 fn into_abi(self) -> T::MaybeAbi {
799 match self {
800 None => T::none(),
801 Some(me) => me.into_maybe_abi(),
802 }
803 }
804}
805
806impl<T: MaybeFromWasmAbi> FromWasmAbi for Option<T> {
807 type Abi = T::MaybeAbi;
808
809 #[inline]
810 unsafe fn from_abi(js: T::MaybeAbi) -> Self {
811 if T::is_none(&js) {
812 None
813 } else {
814 Some(T::from_maybe_abi(js))
815 }
816 }
817
818 #[inline]
819 unsafe fn try_from_abi(js: T::MaybeAbi) -> Result<Self, &'static str> {
820 if T::is_none(&js) {
821 Ok(None)
822 } else {
823 T::try_from_maybe_abi(js).map(Some)
824 }
825 }
826}
827
828impl<T: NullableIntoWasmAbi> IntoWasmAbi for Nullable<T> {
829 type Abi = T::MaybeAbi;
830
831 #[inline]
832 fn into_abi(self) -> T::MaybeAbi {
833 match self {
834 Nullable::Null => T::null(),
835 Nullable::Value(me) => me.into_maybe_abi(),
836 }
837 }
838}
839
840impl<T: NullableIntoWasmAbi> OptionIntoWasmAbi for Nullable<T> {
842 #[inline]
843 fn none() -> T::MaybeAbi {
844 T::none()
845 }
846}
847
848impl<T: NullableFromWasmAbi> FromWasmAbi for Nullable<T> {
849 type Abi = T::MaybeAbi;
850
851 #[inline]
852 unsafe fn from_abi(js: T::MaybeAbi) -> Self {
853 if T::is_null(&js) {
854 Nullable::Null
855 } else {
856 Nullable::Value(T::from_maybe_abi(js))
857 }
858 }
859
860 #[inline]
861 unsafe fn try_from_abi(js: T::MaybeAbi) -> Result<Self, &'static str> {
862 if T::is_null(&js) {
863 Ok(Nullable::Null)
864 } else {
865 T::try_from_maybe_abi(js).map(Nullable::Value)
866 }
867 }
868}
869
870impl<T: NullableFromWasmAbi> OptionFromWasmAbi for Nullable<T> {
873 #[inline]
874 fn is_none(js: &T::MaybeAbi) -> bool {
875 !T::is_null(js) && T::is_none(js)
876 }
877}
878
879unsafe impl<T: ErasableGeneric> ErasableGeneric for Nullable<T> {
880 type Repr = Nullable<<T as ErasableGeneric>::Repr>;
881}
882
883impl<T, Target> UpcastFrom<Nullable<T>> for Nullable<Target> where Target: UpcastFrom<T> {}
884impl<T, Target> UpcastFrom<Nullable<T>> for Option<Target> where Target: UpcastFrom<T> {}
889impl<T, Target> UpcastFrom<Nullable<T>> for JsOption<Nullable<Target>> where Target: UpcastFrom<T> {}
890impl<T, Target> UpcastFrom<Nullable<T>> for JsNullable<Nullable<Target>> where Target: UpcastFrom<T> {}
891impl<T> UpcastFrom<Nullable<T>> for JsValue where JsValue: UpcastFrom<T> {}
892
893impl<T: Promising> Promising for Option<T> {
894 type Resolution = Option<<T as Promising>::Resolution>;
895}
896
897impl<T: Promising> Promising for Nullable<T> {
898 type Resolution = Nullable<<T as Promising>::Resolution>;
899}
900
901impl<T: IntoWasmAbi> IntoWasmAbi for Clamped<T> {
902 type Abi = T::Abi;
903
904 #[inline]
905 fn into_abi(self) -> Self::Abi {
906 self.0.into_abi()
907 }
908}
909
910impl<T: FromWasmAbi> FromWasmAbi for Clamped<T> {
911 type Abi = T::Abi;
912
913 #[inline]
914 unsafe fn from_abi(js: T::Abi) -> Self {
915 Clamped(T::from_abi(js))
916 }
917
918 #[inline]
919 unsafe fn try_from_abi(js: T::Abi) -> Result<Self, &'static str> {
920 T::try_from_abi(js).map(Clamped)
921 }
922}
923
924impl IntoWasmAbi for () {
925 type Abi = ();
926
927 #[inline]
928 fn into_abi(self) {
929 self
930 }
931}
932
933impl FromWasmAbi for () {
934 type Abi = ();
935
936 #[inline]
937 unsafe fn from_abi(_js: ()) {}
938}
939
940impl Promising for () {
941 type Resolution = Undefined;
942}
943
944impl UpcastFrom<()> for JsValue {}
945impl UpcastFrom<()> for () {}
946impl<T> UpcastFrom<()> for Option<T> {}
948
949unsafe impl ErasableGeneric for () {
950 type Repr = ();
951}
952
953impl<T: WasmAbi<Prim3 = (), Prim4 = ()>> WasmAbi for Result<T, u32> {
954 type Prim1 = T::Prim1;
955 type Prim2 = T::Prim2;
956 type Prim3 = u32;
961 type Prim4 = u32;
963
964 #[inline]
965 fn split(self) -> (T::Prim1, T::Prim2, u32, u32) {
966 match self {
967 Ok(value) => {
968 let (prim1, prim2, (), ()) = value.split();
969 (prim1, prim2, 0, 0)
970 }
971 Err(err) => (Default::default(), Default::default(), err, 1),
972 }
973 }
974
975 #[inline]
976 fn join(prim1: T::Prim1, prim2: T::Prim2, err: u32, is_err: u32) -> Self {
977 if is_err == 0 {
978 Ok(T::join(prim1, prim2, (), ()))
979 } else {
980 Err(err)
981 }
982 }
983}
984
985impl<T, E> ReturnWasmAbi for Result<T, E>
986where
987 T: IntoWasmAbi,
988 E: Into<JsValue>,
989 T::Abi: WasmAbi<Prim3 = (), Prim4 = ()>,
990{
991 type Abi = Result<T::Abi, u32>;
992
993 #[inline]
994 fn return_abi(self) -> Self::Abi {
995 match self {
996 Ok(v) => Ok(v.into_abi()),
997 Err(e) => {
998 let jsval = e.into();
999 Err(jsval.into_abi())
1000 }
1001 }
1002 }
1003}
1004
1005unsafe impl<T: ErasableGeneric, E: ErasableGeneric> ErasableGeneric for Result<T, E> {
1006 type Repr = Result<<T as ErasableGeneric>::Repr, <E as ErasableGeneric>::Repr>;
1007}
1008
1009impl<T: Promising, E> Promising for Result<T, E> {
1010 type Resolution = Result<<T as Promising>::Resolution, E>;
1011}
1012
1013impl<T, E, TargetT, TargetE> UpcastFrom<Result<T, E>> for Result<TargetT, TargetE>
1014where
1015 TargetT: UpcastFrom<T>,
1016 TargetE: UpcastFrom<E>,
1017{
1018}
1019impl<T, E, TargetT, TargetE> UpcastFrom<Result<T, E>> for JsOption<Result<TargetT, TargetE>>
1020where
1021 TargetT: UpcastFrom<T>,
1022 TargetE: UpcastFrom<E>,
1023{
1024}
1025impl<T, E, TargetT, TargetE> UpcastFrom<Result<T, E>> for JsNullable<Result<TargetT, TargetE>>
1026where
1027 TargetT: UpcastFrom<T>,
1028 TargetE: UpcastFrom<E>,
1029{
1030}
1031
1032unsafe impl ErasableGeneric for JsError {
1033 type Repr = JsValue;
1034}
1035
1036impl IntoWasmAbi for JsError {
1037 type Abi = <JsValue as IntoWasmAbi>::Abi;
1038
1039 fn into_abi(self) -> Self::Abi {
1040 self.value.into_abi()
1041 }
1042}
1043
1044impl FromWasmAbi for JsError {
1046 type Abi = <JsValue as FromWasmAbi>::Abi;
1047
1048 #[inline]
1049 unsafe fn from_abi(js: Self::Abi) -> Self {
1050 JsError {
1051 value: JsValue::from_abi(js),
1052 }
1053 }
1054}
1055
1056impl Promising for JsError {
1057 type Resolution = JsError;
1058}
1059
1060impl UpcastFrom<JsError> for JsValue {}
1061impl UpcastFrom<JsError> for JsOption<JsValue> {}
1062impl UpcastFrom<JsError> for JsNullable<JsValue> {}
1063impl UpcastFrom<JsError> for JsError {}
1064
1065pub fn js_value_vector_into_abi<T: Into<JsValue>>(
1079 vector: Box<[T]>,
1080) -> <Box<[JsValue]> as IntoWasmAbi>::Abi {
1081 let js_vals: Box<[JsValue]> = vector.into_vec().into_iter().map(|x| x.into()).collect();
1082
1083 js_vals.into_abi()
1084}
1085
1086pub unsafe fn js_value_vector_from_abi<T: TryFromJsValue>(
1095 js: <Box<[JsValue]> as FromWasmAbi>::Abi,
1096) -> Box<[T]> {
1097 match try_js_value_vector_from_abi(js) {
1101 Ok(result) => result,
1102 Err(msg) => throw_str(msg),
1103 }
1104}
1105
1106pub unsafe fn try_js_value_vector_from_abi<T: TryFromJsValue>(
1118 js: <Box<[JsValue]> as FromWasmAbi>::Abi,
1119) -> Result<Box<[T]>, &'static str> {
1120 <Vec<JsValue> as FromWasmAbi>::from_abi(js)
1121 .into_iter()
1122 .map(|value| T::try_from_js_value(value).map_err(|_| crate::__rt::WRONG_TYPE_ERROR))
1123 .collect()
1124}