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::convert::traits::{WasmAbi, WasmPrimitive};
9use crate::convert::{
10 FromWasmAbi, IntoWasmAbi, LongRefFromWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi,
11 RefFromWasmAbi, ReturnWasmAbi, TryFromJsValue, UpcastFrom,
12};
13use crate::sys::Promising;
14use crate::sys::{JsOption, Undefined};
15use crate::{Clamped, JsError, JsValue, UnwrapThrowExt, __wbindgen_object_is_undefined};
16
17impl<T: WasmPrimitive> WasmAbi for T {
19 type Prim1 = Self;
20 type Prim2 = ();
21 type Prim3 = ();
22 type Prim4 = ();
23
24 #[inline]
25 fn split(self) -> (Self, (), (), ()) {
26 (self, (), (), ())
27 }
28
29 #[inline]
30 fn join(prim: Self, _: (), _: (), _: ()) -> Self {
31 prim
32 }
33}
34
35impl WasmAbi for i128 {
36 type Prim1 = u64;
37 type Prim2 = u64;
38 type Prim3 = ();
39 type Prim4 = ();
40
41 #[inline]
42 fn split(self) -> (u64, u64, (), ()) {
43 let low = self as u64;
44 let high = (self >> 64) as u64;
45 (low, high, (), ())
46 }
47
48 #[inline]
49 fn join(low: u64, high: u64, _: (), _: ()) -> Self {
50 ((high as u128) << 64 | low as u128) as i128
51 }
52}
53impl WasmAbi for u128 {
54 type Prim1 = u64;
55 type Prim2 = u64;
56 type Prim3 = ();
57 type Prim4 = ();
58
59 #[inline]
60 fn split(self) -> (u64, u64, (), ()) {
61 let low = self as u64;
62 let high = (self >> 64) as u64;
63 (low, high, (), ())
64 }
65
66 #[inline]
67 fn join(low: u64, high: u64, _: (), _: ()) -> Self {
68 (high as u128) << 64 | low as u128
69 }
70}
71
72impl<T: WasmAbi<Prim4 = ()>> WasmAbi for Option<T> {
73 type Prim1 = u32;
75 type Prim2 = T::Prim1;
76 type Prim3 = T::Prim2;
77 type Prim4 = T::Prim3;
78
79 #[inline]
80 fn split(self) -> (u32, T::Prim1, T::Prim2, T::Prim3) {
81 match self {
82 None => (
83 0,
84 Default::default(),
85 Default::default(),
86 Default::default(),
87 ),
88 Some(value) => {
89 let (prim1, prim2, prim3, ()) = value.split();
90 (1, prim1, prim2, prim3)
91 }
92 }
93 }
94
95 #[inline]
96 fn join(is_some: u32, prim1: T::Prim1, prim2: T::Prim2, prim3: T::Prim3) -> Self {
97 if is_some == 0 {
98 None
99 } else {
100 Some(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 IntoWasmAbi for Option<$t> {
122 type Abi = Option<$c>;
123
124 #[inline]
125 fn into_abi(self) -> Self::Abi {
126 self.map(|v| v as $c)
127 }
128 }
129
130 impl FromWasmAbi for Option<$t> {
131 type Abi = Option<$c>;
132
133 #[inline]
134 unsafe fn from_abi(js: Self::Abi) -> Self {
135 js.map(|v: $c| v as $t)
136 }
137 }
138
139 impl UpcastFrom<$t> for JsValue {}
140 impl UpcastFrom<$t> for JsOption<JsValue> {}
141 impl UpcastFrom<$t> for $t {}
142 )*)
143}
144
145type_wasm_native!(
146 i64 as i64
147 u64 as u64
148 i128 as i128
149 u128 as u128
150 f64 as f64
151);
152
153impl UpcastFrom<u64> for u128 {}
154impl UpcastFrom<u64> for JsOption<u128> {}
155impl UpcastFrom<i64> for i128 {}
156impl UpcastFrom<i64> for JsOption<i128> {}
157
158const F64_ABI_OPTION_SENTINEL: f64 = 4294967297_f64;
166
167macro_rules! type_wasm_native_f64_option {
168 ($($t:tt as $c:tt)*) => ($(
169 impl IntoWasmAbi for $t {
170 type Abi = $c;
171
172 #[inline]
173 fn into_abi(self) -> $c { self as $c }
174 }
175
176 impl FromWasmAbi for $t {
177 type Abi = $c;
178
179 #[inline]
180 unsafe fn from_abi(js: $c) -> Self { js as $t }
181 }
182
183 unsafe impl ErasableGeneric for $t {
184 type Repr = $t;
185 }
186
187 impl Promising for $t {
188 type Resolution = $t;
189 }
190
191 impl IntoWasmAbi for Option<$t> {
192 type Abi = f64;
193
194 #[inline]
195 fn into_abi(self) -> Self::Abi {
196 self.map(|v| v as $c as f64).unwrap_or(F64_ABI_OPTION_SENTINEL)
197 }
198 }
199
200 impl FromWasmAbi for Option<$t> {
201 type Abi = f64;
202
203 #[inline]
204 unsafe fn from_abi(js: Self::Abi) -> Self {
205 if js == F64_ABI_OPTION_SENTINEL {
206 None
207 } else {
208 Some(js as $c as $t)
209 }
210 }
211 }
212
213 impl UpcastFrom<$t> for JsValue {}
214 impl UpcastFrom<$t> for JsOption<JsValue> {}
215 impl UpcastFrom<$t> for $t {}
216 )*)
217}
218
219type_wasm_native_f64_option!(
220 i32 as i32
221 isize as i32
222 u32 as u32
223 usize as u32
224 f32 as f32
225);
226
227#[cfg(target_pointer_width = "32")]
228impl UpcastFrom<isize> for i32 {}
229#[cfg(target_pointer_width = "32")]
230impl UpcastFrom<isize> for JsOption<i32> {}
231
232impl UpcastFrom<isize> for i64 {}
233impl UpcastFrom<isize> for JsOption<i64> {}
234impl UpcastFrom<isize> for i128 {}
235impl UpcastFrom<isize> for JsOption<i128> {}
236
237impl UpcastFrom<i32> for isize {}
238impl UpcastFrom<i32> for JsOption<isize> {}
239impl UpcastFrom<i32> for i64 {}
240impl UpcastFrom<i32> for JsOption<i64> {}
241impl UpcastFrom<i32> for i128 {}
242impl UpcastFrom<i32> for JsOption<i128> {}
243
244impl UpcastFrom<u32> for usize {}
245impl UpcastFrom<u32> for JsOption<usize> {}
246impl UpcastFrom<u32> for u64 {}
247impl UpcastFrom<u32> for JsOption<u64> {}
248impl UpcastFrom<u32> for u128 {}
249impl UpcastFrom<u32> for JsOption<u128> {}
250
251#[cfg(target_pointer_width = "32")]
252impl UpcastFrom<usize> for u32 {}
253#[cfg(target_pointer_width = "32")]
254impl UpcastFrom<usize> for JsOption<u32> {}
255impl UpcastFrom<usize> for u64 {}
256impl UpcastFrom<usize> for JsOption<u64> {}
257impl UpcastFrom<usize> for u128 {}
258impl UpcastFrom<usize> for JsOption<u128> {}
259
260impl UpcastFrom<f32> for f64 {}
261impl UpcastFrom<f32> for JsOption<f64> {}
262
263const U32_ABI_OPTION_SENTINEL: u32 = 0x00FF_FFFFu32;
269
270macro_rules! type_abi_as_u32 {
271 ($($t:tt)*) => ($(
272 impl IntoWasmAbi for $t {
273 type Abi = u32;
274
275 #[inline]
276 fn into_abi(self) -> u32 { self as u32 }
277 }
278
279 impl FromWasmAbi for $t {
280 type Abi = u32;
281
282 #[inline]
283 unsafe fn from_abi(js: u32) -> Self { js as $t }
284 }
285
286 impl OptionIntoWasmAbi for $t {
287 #[inline]
288 fn none() -> u32 { U32_ABI_OPTION_SENTINEL }
289 }
290
291 impl OptionFromWasmAbi for $t {
292 #[inline]
293 fn is_none(js: &u32) -> bool { *js == U32_ABI_OPTION_SENTINEL }
294 }
295
296 unsafe impl ErasableGeneric for $t {
297 type Repr = $t;
298 }
299
300 impl Promising for $t {
301 type Resolution = $t;
302 }
303
304 impl UpcastFrom<$t> for JsValue {}
305 impl UpcastFrom<$t> for JsOption<JsValue> {}
306 impl UpcastFrom<$t> for $t {}
307 )*)
308}
309
310type_abi_as_u32!(i8 u8 i16 u16);
311
312impl UpcastFrom<i8> for i16 {}
313impl UpcastFrom<i8> for JsOption<i16> {}
314impl UpcastFrom<i8> for i32 {}
315impl UpcastFrom<i8> for JsOption<i32> {}
316impl UpcastFrom<i8> for i64 {}
317impl UpcastFrom<i8> for JsOption<i64> {}
318impl UpcastFrom<i8> for i128 {}
319impl UpcastFrom<i8> for JsOption<i128> {}
320
321impl UpcastFrom<u8> for u16 {}
322impl UpcastFrom<u8> for JsOption<u16> {}
323impl UpcastFrom<u8> for u32 {}
324impl UpcastFrom<u8> for JsOption<u32> {}
325impl UpcastFrom<u8> for u64 {}
326impl UpcastFrom<u8> for JsOption<u64> {}
327impl UpcastFrom<u8> for u128 {}
328impl UpcastFrom<u8> for JsOption<u128> {}
329
330impl UpcastFrom<i16> for i32 {}
331impl UpcastFrom<i16> for JsOption<i32> {}
332impl UpcastFrom<i16> for i64 {}
333impl UpcastFrom<i16> for JsOption<i64> {}
334impl UpcastFrom<i16> for i128 {}
335impl UpcastFrom<i16> for JsOption<i128> {}
336
337impl UpcastFrom<u16> for u32 {}
338impl UpcastFrom<u16> for JsOption<u32> {}
339impl UpcastFrom<u16> for u64 {}
340impl UpcastFrom<u16> for JsOption<u64> {}
341impl UpcastFrom<u16> for u128 {}
342impl UpcastFrom<u16> for JsOption<u128> {}
343
344impl IntoWasmAbi for bool {
345 type Abi = u32;
346
347 #[inline]
348 fn into_abi(self) -> u32 {
349 self as u32
350 }
351}
352
353impl FromWasmAbi for bool {
354 type Abi = u32;
355
356 #[inline]
357 unsafe fn from_abi(js: u32) -> bool {
358 js != 0
359 }
360}
361
362impl OptionIntoWasmAbi for bool {
363 #[inline]
364 fn none() -> u32 {
365 U32_ABI_OPTION_SENTINEL
366 }
367}
368
369impl OptionFromWasmAbi for bool {
370 #[inline]
371 fn is_none(js: &u32) -> bool {
372 *js == U32_ABI_OPTION_SENTINEL
373 }
374}
375
376unsafe impl ErasableGeneric for bool {
377 type Repr = bool;
378}
379
380impl Promising for bool {
381 type Resolution = bool;
382}
383
384impl UpcastFrom<bool> for JsValue {}
385impl UpcastFrom<bool> for JsOption<JsValue> {}
386impl UpcastFrom<bool> for bool {}
387
388impl IntoWasmAbi for char {
389 type Abi = u32;
390
391 #[inline]
392 fn into_abi(self) -> u32 {
393 self as u32
394 }
395}
396
397impl FromWasmAbi for char {
398 type Abi = u32;
399
400 #[inline]
401 unsafe fn from_abi(js: u32) -> char {
402 char::from_u32_unchecked(js)
404 }
405}
406
407impl OptionIntoWasmAbi for char {
408 #[inline]
409 fn none() -> u32 {
410 U32_ABI_OPTION_SENTINEL
411 }
412}
413
414impl OptionFromWasmAbi for char {
415 #[inline]
416 fn is_none(js: &u32) -> bool {
417 *js == U32_ABI_OPTION_SENTINEL
418 }
419}
420
421unsafe impl ErasableGeneric for char {
422 type Repr = char;
423}
424
425impl Promising for char {
426 type Resolution = char;
427}
428
429impl UpcastFrom<char> for JsValue {}
430impl UpcastFrom<char> for JsOption<JsValue> {}
431impl UpcastFrom<char> for char {}
432
433impl<T> IntoWasmAbi for *const T {
434 type Abi = u32;
435
436 #[inline]
437 fn into_abi(self) -> u32 {
438 self as u32
439 }
440}
441
442impl<T> FromWasmAbi for *const T {
443 type Abi = u32;
444
445 #[inline]
446 unsafe fn from_abi(js: u32) -> *const T {
447 js as *const T
448 }
449}
450
451unsafe impl<T: ErasableGeneric> ErasableGeneric for *const T {
452 type Repr = *const T::Repr;
453}
454
455impl<T, Target> UpcastFrom<*const T> for *const Target where Target: UpcastFrom<T> {}
456impl<T, Target> UpcastFrom<*const T> for JsOption<*const Target> where Target: UpcastFrom<T> {}
457
458impl<T> IntoWasmAbi for Option<*const T> {
459 type Abi = f64;
460
461 #[inline]
462 fn into_abi(self) -> f64 {
463 self.map(|ptr| ptr as u32 as f64)
464 .unwrap_or(F64_ABI_OPTION_SENTINEL)
465 }
466}
467
468unsafe impl<T: ErasableGeneric> ErasableGeneric for Option<T> {
469 type Repr = Option<<T as ErasableGeneric>::Repr>;
470}
471
472impl<T, Target> UpcastFrom<Option<T>> for Option<Target> where Target: UpcastFrom<T> {}
473impl<T, Target> UpcastFrom<Option<T>> for JsOption<Option<Target>> where Target: UpcastFrom<T> {}
474
475impl<T> FromWasmAbi for Option<*const T> {
476 type Abi = f64;
477
478 #[inline]
479 unsafe fn from_abi(js: f64) -> Option<*const T> {
480 if js == F64_ABI_OPTION_SENTINEL {
481 None
482 } else {
483 Some(js as u32 as *const T)
484 }
485 }
486}
487
488impl<T> IntoWasmAbi for *mut T {
489 type Abi = u32;
490
491 #[inline]
492 fn into_abi(self) -> u32 {
493 self as u32
494 }
495}
496
497impl<T> FromWasmAbi for *mut T {
498 type Abi = u32;
499
500 #[inline]
501 unsafe fn from_abi(js: u32) -> *mut T {
502 js as *mut T
503 }
504}
505
506impl<T> IntoWasmAbi for Option<*mut T> {
507 type Abi = f64;
508
509 #[inline]
510 fn into_abi(self) -> f64 {
511 self.map(|ptr| ptr as u32 as f64)
512 .unwrap_or(F64_ABI_OPTION_SENTINEL)
513 }
514}
515
516impl<T> FromWasmAbi for Option<*mut T> {
517 type Abi = f64;
518
519 #[inline]
520 unsafe fn from_abi(js: f64) -> Option<*mut T> {
521 if js == F64_ABI_OPTION_SENTINEL {
522 None
523 } else {
524 Some(js as u32 as *mut T)
525 }
526 }
527}
528
529impl<T> IntoWasmAbi for NonNull<T> {
530 type Abi = u32;
531
532 #[inline]
533 fn into_abi(self) -> u32 {
534 self.as_ptr() as u32
535 }
536}
537
538impl<T> OptionIntoWasmAbi for NonNull<T> {
539 #[inline]
540 fn none() -> u32 {
541 0
542 }
543}
544
545impl<T> FromWasmAbi for NonNull<T> {
546 type Abi = u32;
547
548 #[inline]
549 unsafe fn from_abi(js: Self::Abi) -> Self {
550 NonNull::new_unchecked(js as *mut T)
552 }
553}
554
555impl<T> OptionFromWasmAbi for NonNull<T> {
556 #[inline]
557 fn is_none(js: &u32) -> bool {
558 *js == 0
559 }
560}
561
562impl IntoWasmAbi for JsValue {
563 type Abi = u32;
564
565 #[inline]
566 fn into_abi(self) -> u32 {
567 let ret = self.idx;
568 mem::forget(self);
569 ret
570 }
571}
572
573impl FromWasmAbi for JsValue {
574 type Abi = u32;
575
576 #[inline]
577 unsafe fn from_abi(js: u32) -> JsValue {
578 JsValue::_new(js)
579 }
580}
581
582impl IntoWasmAbi for &JsValue {
583 type Abi = u32;
584
585 #[inline]
586 fn into_abi(self) -> u32 {
587 self.idx
588 }
589}
590
591impl RefFromWasmAbi for JsValue {
592 type Abi = u32;
593 type Anchor = ManuallyDrop<JsValue>;
594
595 #[inline]
596 unsafe fn ref_from_abi(js: u32) -> Self::Anchor {
597 ManuallyDrop::new(JsValue::_new(js))
598 }
599}
600
601impl LongRefFromWasmAbi for JsValue {
602 type Abi = u32;
603 type Anchor = JsValue;
604
605 #[inline]
606 unsafe fn long_ref_from_abi(js: u32) -> Self::Anchor {
607 Self::from_abi(js)
608 }
609}
610
611impl OptionIntoWasmAbi for JsValue {
612 #[inline]
613 fn none() -> u32 {
614 crate::__rt::JSIDX_UNDEFINED
615 }
616}
617
618impl OptionIntoWasmAbi for &JsValue {
619 #[inline]
620 fn none() -> u32 {
621 crate::__rt::JSIDX_UNDEFINED
622 }
623}
624
625impl OptionFromWasmAbi for JsValue {
626 #[inline]
627 fn is_none(js: &u32) -> bool {
628 unsafe { __wbindgen_object_is_undefined(*js) }
629 }
630}
631
632impl<T: OptionIntoWasmAbi> IntoWasmAbi for Option<T> {
633 type Abi = T::Abi;
634
635 #[inline]
636 fn into_abi(self) -> T::Abi {
637 match self {
638 None => T::none(),
639 Some(me) => me.into_abi(),
640 }
641 }
642}
643
644impl<T: OptionFromWasmAbi> FromWasmAbi for Option<T> {
645 type Abi = T::Abi;
646
647 #[inline]
648 unsafe fn from_abi(js: T::Abi) -> Self {
649 if T::is_none(&js) {
650 None
651 } else {
652 Some(T::from_abi(js))
653 }
654 }
655}
656
657impl<T: OptionIntoWasmAbi + ErasableGeneric<Repr = JsValue> + Promising> Promising for Option<T> {
658 type Resolution = Option<<T as Promising>::Resolution>;
659}
660
661impl<T: IntoWasmAbi> IntoWasmAbi for Clamped<T> {
662 type Abi = T::Abi;
663
664 #[inline]
665 fn into_abi(self) -> Self::Abi {
666 self.0.into_abi()
667 }
668}
669
670impl<T: FromWasmAbi> FromWasmAbi for Clamped<T> {
671 type Abi = T::Abi;
672
673 #[inline]
674 unsafe fn from_abi(js: T::Abi) -> Self {
675 Clamped(T::from_abi(js))
676 }
677}
678
679impl IntoWasmAbi for () {
680 type Abi = ();
681
682 #[inline]
683 fn into_abi(self) {
684 self
685 }
686}
687
688impl FromWasmAbi for () {
689 type Abi = ();
690
691 #[inline]
692 unsafe fn from_abi(_js: ()) {}
693}
694
695impl Promising for () {
696 type Resolution = Undefined;
697}
698
699impl UpcastFrom<()> for JsValue {}
700impl UpcastFrom<()> for () {}
701
702unsafe impl ErasableGeneric for () {
703 type Repr = ();
704}
705
706impl<T: WasmAbi<Prim3 = (), Prim4 = ()>> WasmAbi for Result<T, u32> {
707 type Prim1 = T::Prim1;
708 type Prim2 = T::Prim2;
709 type Prim3 = u32;
714 type Prim4 = u32;
716
717 #[inline]
718 fn split(self) -> (T::Prim1, T::Prim2, u32, u32) {
719 match self {
720 Ok(value) => {
721 let (prim1, prim2, (), ()) = value.split();
722 (prim1, prim2, 0, 0)
723 }
724 Err(err) => (Default::default(), Default::default(), err, 1),
725 }
726 }
727
728 #[inline]
729 fn join(prim1: T::Prim1, prim2: T::Prim2, err: u32, is_err: u32) -> Self {
730 if is_err == 0 {
731 Ok(T::join(prim1, prim2, (), ()))
732 } else {
733 Err(err)
734 }
735 }
736}
737
738impl<T, E> ReturnWasmAbi for Result<T, E>
739where
740 T: IntoWasmAbi,
741 E: Into<JsValue>,
742 T::Abi: WasmAbi<Prim3 = (), Prim4 = ()>,
743{
744 type Abi = Result<T::Abi, u32>;
745
746 #[inline]
747 fn return_abi(self) -> Self::Abi {
748 match self {
749 Ok(v) => Ok(v.into_abi()),
750 Err(e) => {
751 let jsval = e.into();
752 Err(jsval.into_abi())
753 }
754 }
755 }
756}
757
758unsafe impl<T: ErasableGeneric, E: ErasableGeneric> ErasableGeneric for Result<T, E> {
759 type Repr = Result<<T as ErasableGeneric>::Repr, <E as ErasableGeneric>::Repr>;
760}
761
762impl<T: ErasableGeneric + Promising, E: ErasableGeneric> Promising for Result<T, E> {
763 type Resolution = Result<<T as Promising>::Resolution, E>;
764}
765
766impl<T, E, TargetT, TargetE> UpcastFrom<Result<T, E>> for Result<TargetT, TargetE>
767where
768 TargetT: UpcastFrom<T>,
769 TargetE: UpcastFrom<E>,
770{
771}
772impl<T, E, TargetT, TargetE> UpcastFrom<Result<T, E>> for JsOption<Result<TargetT, TargetE>>
773where
774 TargetT: UpcastFrom<T>,
775 TargetE: UpcastFrom<E>,
776{
777}
778
779unsafe impl ErasableGeneric for JsError {
780 type Repr = JsValue;
781}
782
783impl IntoWasmAbi for JsError {
784 type Abi = <JsValue as IntoWasmAbi>::Abi;
785
786 fn into_abi(self) -> Self::Abi {
787 self.value.into_abi()
788 }
789}
790
791impl Promising for JsError {
792 type Resolution = JsError;
793}
794
795impl UpcastFrom<JsError> for JsValue {}
796impl UpcastFrom<JsError> for JsOption<JsValue> {}
797impl UpcastFrom<JsError> for JsError {}
798
799pub fn js_value_vector_into_abi<T: Into<JsValue>>(
807 vector: Box<[T]>,
808) -> <Box<[JsValue]> as IntoWasmAbi>::Abi {
809 let js_vals: Box<[JsValue]> = vector.into_vec().into_iter().map(|x| x.into()).collect();
810
811 js_vals.into_abi()
812}
813
814pub unsafe fn js_value_vector_from_abi<T: TryFromJsValue>(
820 js: <Box<[JsValue]> as FromWasmAbi>::Abi,
821) -> Box<[T]> {
822 let js_vals = <Vec<JsValue> as FromWasmAbi>::from_abi(js);
823
824 let mut result = Vec::with_capacity(js_vals.len());
825 for value in js_vals {
826 result.push(
837 T::try_from_js_value(value).expect_throw("array contains a value of the wrong type"),
838 );
839 }
840 result.into_boxed_slice()
841}