1use alloc::borrow::Cow;
2use alloc::boxed::Box;
3use alloc::string::String;
4use alloc::vec::Vec;
5use core::mem::{self, MaybeUninit};
6use core::ops::{Deref, DerefMut};
7use core::str;
8
9use crate::__rt::{marker::ErasableGeneric, WasmWord};
10use crate::__wbindgen_copy_to_typed_array;
11use crate::convert::{
12 js_value_vector_from_abi, js_value_vector_into_abi, try_js_value_vector_from_abi, FromWasmAbi,
13 IntoWasmAbi, LongRefFromWasmAbi, MaybeIntoWasmAbi, NullableIntoWasmAbi, OptionFromWasmAbi,
14 OptionIntoWasmAbi, RefFromWasmAbi, RefMutFromWasmAbi, UpcastFrom, VectorFromWasmAbi,
15 VectorIntoWasmAbi, WasmAbi,
16};
17use crate::describe::*;
18use crate::sys::{JsNullable, JsOption};
19use crate::{JsError, JsValue, Nullable};
20
21use cfg_if::cfg_if;
22
23#[repr(C)]
32#[derive(Clone, Copy)]
33pub struct WasmSlice {
34 pub ptr: WasmWord,
35 pub len: WasmWord,
36}
37
38impl WasmSlice {
39 #[inline]
40 pub fn from_usize(ptr: usize, len: usize) -> Self {
41 Self {
42 ptr: WasmWord::from_usize(ptr),
43 len: WasmWord::from_usize(len),
44 }
45 }
46}
47
48impl WasmAbi for WasmSlice {
49 type Prim1 = <WasmWord as WasmAbi>::Prim1;
51 type Prim2 = <WasmWord as WasmAbi>::Prim1;
53 type Prim3 = ();
54 type Prim4 = ();
55
56 #[inline]
57 fn split(self) -> (Self::Prim1, Self::Prim2, (), ()) {
58 (self.ptr.split().0, self.len.split().0, (), ())
59 }
60
61 #[inline]
62 fn join(ptr: Self::Prim1, len: Self::Prim2, _: (), _: ()) -> Self {
63 Self {
64 ptr: WasmWord::join(ptr, (), (), ()),
65 len: WasmWord::join(len, (), (), ()),
66 }
67 }
68}
69
70#[inline]
71fn null_slice() -> WasmSlice {
72 WasmSlice::from_usize(0, 0)
73}
74
75#[inline]
78fn js_null_slice() -> WasmSlice {
79 WasmSlice::from_usize(0, crate::__rt::JSIDX_NULL as usize)
80}
81
82#[inline]
83fn is_js_null_slice(slice: &WasmSlice) -> bool {
84 slice.ptr.is_zero() && slice.len.into_usize() == crate::__rt::JSIDX_NULL as usize
85}
86
87pub struct WasmMutSlice {
88 pub slice: WasmSlice,
89 pub idx: u32,
90}
91
92impl WasmAbi for WasmMutSlice {
93 type Prim1 = <WasmSlice as WasmAbi>::Prim1;
95 type Prim2 = <WasmSlice as WasmAbi>::Prim2;
97 type Prim3 = u32;
99 type Prim4 = ();
100
101 #[inline]
102 fn split(self) -> (Self::Prim1, Self::Prim2, u32, ()) {
103 let (ptr, len, (), ()) = self.slice.split();
104 (ptr, len, self.idx, ())
105 }
106
107 #[inline]
108 fn join(ptr: Self::Prim1, len: Self::Prim2, idx: u32, _: ()) -> Self {
109 Self {
110 slice: WasmSlice::join(ptr, len, (), ()),
111 idx,
112 }
113 }
114}
115
116pub struct MutSlice<T> {
118 contents: Box<[T]>,
120 js: JsValue,
122}
123
124impl<T> Drop for MutSlice<T> {
125 fn drop(&mut self) {
126 let byte_slice = unsafe {
127 core::slice::from_raw_parts(
128 self.contents.as_ptr() as *const u8,
129 self.contents.len() * mem::size_of::<T>(),
130 )
131 };
132 __wbindgen_copy_to_typed_array(byte_slice, &self.js);
133 }
134}
135
136impl<T> Deref for MutSlice<T> {
137 type Target = [T];
138
139 fn deref(&self) -> &[T] {
140 &self.contents
141 }
142}
143
144impl<T> DerefMut for MutSlice<T> {
145 fn deref_mut(&mut self) -> &mut [T] {
146 &mut self.contents
147 }
148}
149
150macro_rules! vectors {
151 ($($t:ty)*) => ($(
152 vectors_internal!($t);
153 vectors_internal!(MaybeUninit<$t>);
154 )*)
155}
156
157macro_rules! vectors_internal {
158 ($t:ty) => {
159 impl WasmDescribeVector for $t {
160 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
161 fn describe_vector() {
162 inform(VECTOR);
163 <$t>::describe();
164 }
165 }
166
167 impl VectorIntoWasmAbi for $t {
168 type Abi = WasmSlice;
169
170 #[inline]
171 fn vector_into_abi(vector: Box<[$t]>) -> WasmSlice {
172 let ptr = vector.as_ptr();
173 let len = vector.len();
174 mem::forget(vector);
175 WasmSlice::from_usize(ptr as usize, len)
176 }
177 }
178
179 impl VectorFromWasmAbi for $t {
180 type Abi = WasmSlice;
181
182 #[inline]
183 unsafe fn vector_from_abi(js: WasmSlice) -> Box<[$t]> {
184 let ptr = js.ptr.into_usize() as *mut $t;
185 let len = js.len.into_usize();
186 Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
187 }
188 }
189
190 impl VectorRefIntoWasmAbi for $t {
191 #[inline]
192 fn slice_into_abi(slice: &[$t]) -> WasmSlice {
193 WasmSlice::borrow(slice)
194 }
195 }
196
197 impl crate::__rt::marker::VectorRefIntoWasmAbiSealed for $t {}
198
199 impl<'a> IntoWasmAbi for &'a mut [$t] {
200 type Abi = WasmSlice;
201
202 #[inline]
203 fn into_abi(self) -> WasmSlice {
204 (&*self).into_abi()
205 }
206 }
207
208 impl<'a> OptionIntoWasmAbi for &'a mut [$t] {
209 #[inline]
210 fn none() -> WasmSlice {
211 null_slice()
212 }
213 }
214
215 impl_nullable_into_shared_abi!(null = js_null_slice(); ['a] &'a mut [$t]);
216
217 impl RefFromWasmAbi for [$t] {
218 type Abi = WasmSlice;
219 type Anchor = Box<[$t]>;
220
221 #[inline]
222 unsafe fn ref_from_abi(js: WasmSlice) -> Box<[$t]> {
223 <Box<[$t]>>::from_abi(js)
224 }
225 }
226
227 impl RefMutFromWasmAbi for [$t] {
228 type Abi = WasmMutSlice;
229 type Anchor = MutSlice<$t>;
230
231 #[inline]
232 unsafe fn ref_mut_from_abi(js: WasmMutSlice) -> MutSlice<$t> {
233 let contents = <Box<[$t]>>::from_abi(js.slice);
234 let js = JsValue::from_abi(js.idx);
235 MutSlice { contents, js }
236 }
237 }
238
239 impl LongRefFromWasmAbi for [$t] {
240 type Abi = WasmSlice;
241 type Anchor = Box<[$t]>;
242
243 #[inline]
244 unsafe fn long_ref_from_abi(js: WasmSlice) -> Box<[$t]> {
245 Self::ref_from_abi(js)
246 }
247 }
248 };
249}
250
251vectors! {
252 u8 i8 u16 i16 u32 i32 u64 i64 usize isize f32 f64
253}
254
255impl WasmDescribeVector for String {
256 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
257 fn describe_vector() {
258 inform(VECTOR);
259 inform(NAMED_EXTERNREF);
260 inform(6);
262 inform('s' as u32);
263 inform('t' as u32);
264 inform('r' as u32);
265 inform('i' as u32);
266 inform('n' as u32);
267 inform('g' as u32);
268 }
269}
270
271impl VectorIntoWasmAbi for String {
272 type Abi = <Box<[JsValue]> as IntoWasmAbi>::Abi;
273
274 fn vector_into_abi(vector: Box<[Self]>) -> Self::Abi {
275 js_value_vector_into_abi(vector)
276 }
277}
278
279impl VectorFromWasmAbi for String {
280 type Abi = <Box<[JsValue]> as FromWasmAbi>::Abi;
281
282 unsafe fn vector_from_abi(js: Self::Abi) -> Box<[Self]> {
283 js_value_vector_from_abi(js)
284 }
285
286 unsafe fn try_vector_from_abi(js: Self::Abi) -> Result<Box<[Self]>, &'static str> {
287 try_js_value_vector_from_abi(js)
288 }
289}
290
291cfg_if! {
292 if #[cfg(feature = "enable-interning")] {
293 #[inline]
294 fn unsafe_get_cached_str(x: &str) -> Option<WasmSlice> {
295 crate::cache::intern::unsafe_get_str(x).map(|x| WasmSlice::from_usize(0, x as usize))
297 }
298
299 } else {
300 #[inline]
301 fn unsafe_get_cached_str(_x: &str) -> Option<WasmSlice> {
302 None
303 }
304 }
305}
306
307impl<T> IntoWasmAbi for Vec<T>
308where
309 Box<[T]>: IntoWasmAbi<Abi = WasmSlice>,
310{
311 type Abi = <Box<[T]> as IntoWasmAbi>::Abi;
312
313 #[inline]
314 fn into_abi(self) -> Self::Abi {
315 self.into_boxed_slice().into_abi()
316 }
317}
318
319impl<T> OptionIntoWasmAbi for Vec<T>
320where
321 Box<[T]>: IntoWasmAbi<Abi = WasmSlice>,
322{
323 #[inline]
324 fn none() -> WasmSlice {
325 null_slice()
326 }
327}
328
329impl_nullable_into_shared_abi!(
330 null = js_null_slice();
331 [T] Vec<T> where Box<[T]>: IntoWasmAbi<Abi = WasmSlice>
332);
333
334pub trait VectorRefIntoWasmAbi:
345 WasmDescribe + Sized + crate::__rt::marker::VectorRefIntoWasmAbiSealed
346{
347 fn slice_into_abi(slice: &[Self]) -> WasmSlice;
348}
349
350impl<T: VectorRefIntoWasmAbi> IntoWasmAbi for &[T] {
351 type Abi = WasmSlice;
352
353 #[inline]
354 fn into_abi(self) -> WasmSlice {
355 T::slice_into_abi(self)
356 }
357}
358
359impl<T: VectorRefIntoWasmAbi> OptionIntoWasmAbi for &[T] {
360 #[inline]
361 fn none() -> WasmSlice {
362 null_slice()
363 }
364}
365
366impl_nullable_into_shared_abi!(null = js_null_slice(); [T: VectorRefIntoWasmAbi] &[T]);
367
368#[repr(C)]
373struct AbiCell<A: WasmAbi>(A::Prim1, A::Prim2, A::Prim3, A::Prim4);
374
375#[cfg(target_arch = "wasm64")]
377const _: () = assert!(mem::size_of::<AbiCell<WasmSlice>>() == 16);
378#[cfg(target_arch = "wasm64")]
379const _: () = assert!(mem::align_of::<AbiCell<WasmSlice>>() == 8);
380#[cfg(not(target_arch = "wasm64"))]
381const _: () = assert!(mem::size_of::<AbiCell<WasmSlice>>() == 8);
382#[cfg(not(target_arch = "wasm64"))]
383const _: () = assert!(mem::align_of::<AbiCell<WasmSlice>>() == 4);
384
385impl WasmSlice {
386 #[inline]
388 pub fn borrow<T>(slice: &[T]) -> Self {
389 Self::from_usize(slice.as_ptr() as usize, slice.len())
390 }
391
392 pub fn encode<'a, T: IntoWasmAbi + 'a>(
395 slice: &'a [T],
396 mut f: impl FnMut(&'a T) -> T::Abi,
397 ) -> Self {
398 let cells: Box<[AbiCell<T::Abi>]> = slice
399 .iter()
400 .map(|elem| {
401 let (p1, p2, p3, p4) = f(elem).split();
402 AbiCell(p1, p2, p3, p4)
403 })
404 .collect();
405 let len = cells.len();
406 Self::from_usize(Box::into_raw(cells) as *mut AbiCell<T::Abi> as usize, len)
407 }
408
409 pub unsafe fn try_decode<T: FromWasmAbi>(self) -> Result<Box<[T]>, &'static str> {
418 let ptr = self.ptr.into_usize() as *mut AbiCell<T::Abi>;
419 let len = self.len.into_usize();
420 Vec::from_raw_parts(ptr, len, len)
421 .into_iter()
422 .map(|AbiCell(p1, p2, p3, p4)| T::try_from_abi(T::Abi::join(p1, p2, p3, p4)))
423 .collect()
424 }
425}
426
427#[macro_export]
435#[doc(hidden)]
436macro_rules! __wbindgen_encoded_sequence {
437 ($t:ty, $encode:expr, [$($side:ident),+ $(,)?]) => {
438 $($crate::__wbindgen_encoded_sequence!(@$side $t, $encode);)+
439 };
440 (@ref_into $t:ty, $encode:expr) => {
441 $crate::__wbindgen_coverage! {
442 #[automatically_derived]
443 impl $crate::convert::VectorRefIntoWasmAbi for $t {
444 #[inline]
445 fn slice_into_abi(slice: &[Self]) -> $crate::convert::WasmSlice {
446 $crate::convert::WasmSlice::encode(slice, $encode)
447 }
448 }
449 }
450
451 #[automatically_derived]
452 impl $crate::__rt::marker::VectorRefIntoWasmAbiSealed for $t {}
453 };
454 (@into $t:ty, $encode:expr) => {
455 const _: () = assert!(!$crate::__rt::core::mem::needs_drop::<$t>());
456
457 $crate::__wbindgen_coverage! {
458 #[automatically_derived]
459 impl $crate::describe::WasmDescribeVector for $t {
460 fn describe_vector() {
461 $crate::describe::inform($crate::describe::VECTOR);
462 <Self as $crate::describe::WasmDescribe>::describe();
463 }
464 }
465 }
466
467 #[automatically_derived]
468 impl $crate::convert::VectorIntoWasmAbi for $t {
469 type Abi = $crate::convert::WasmSlice;
470
471 #[inline]
472 fn vector_into_abi(
473 vector: $crate::__rt::alloc::boxed::Box<[Self]>,
474 ) -> $crate::convert::WasmSlice {
475 <Self as $crate::convert::VectorRefIntoWasmAbi>::slice_into_abi(&vector)
476 }
477 }
478 };
479 (@from $t:ty, $encode:expr) => {
480 #[automatically_derived]
481 impl $crate::convert::VectorFromWasmAbi for $t {
482 type Abi = $crate::convert::WasmSlice;
483
484 #[inline]
485 unsafe fn vector_from_abi(
486 js: $crate::convert::WasmSlice,
487 ) -> $crate::__rt::alloc::boxed::Box<[Self]> {
488 match js.try_decode() {
491 $crate::__rt::core::result::Result::Ok(decoded) => decoded,
492 $crate::__rt::core::result::Result::Err(msg) => $crate::throw_str(msg),
493 }
494 }
495
496 #[inline]
497 unsafe fn try_vector_from_abi(
498 js: $crate::convert::WasmSlice,
499 ) -> $crate::__rt::core::result::Result<
500 $crate::__rt::alloc::boxed::Box<[Self]>,
501 &'static str,
502 > {
503 js.try_decode()
504 }
505 }
506 };
507}
508
509crate::__wbindgen_encoded_sequence!(bool, |b| (*b).into_abi(), [ref_into, into, from]);
510crate::__wbindgen_encoded_sequence!(char, |c| (*c).into_abi(), [ref_into, into, from]);
511crate::__wbindgen_encoded_sequence!(&str, |s| (*s).into_abi(), [ref_into, into]);
512crate::__wbindgen_encoded_sequence!(&String, |s| (*s).into_abi(), [ref_into]);
513crate::__wbindgen_encoded_sequence!(&Box<str>, |s| (*s).into_abi(), [ref_into]);
514crate::__wbindgen_encoded_sequence!(&Cow<'_, str>, |s| (*s).into_abi(), [ref_into]);
515crate::__wbindgen_encoded_sequence!(String, |s| s.into_abi(), [ref_into]);
517
518impl crate::__rt::marker::VectorRefIntoWasmAbiSealed for JsValue {}
519
520impl VectorRefIntoWasmAbi for JsValue {
521 #[inline]
522 fn slice_into_abi(slice: &[Self]) -> WasmSlice {
523 WasmSlice::borrow(slice)
524 }
525}
526
527impl crate::__rt::marker::VectorRefIntoWasmAbiSealed for JsError {}
528
529impl VectorRefIntoWasmAbi for JsError {
530 #[inline]
531 fn slice_into_abi(slice: &[Self]) -> WasmSlice {
532 WasmSlice::borrow(slice)
533 }
534}
535
536impl<T> FromWasmAbi for Vec<T>
537where
538 Box<[T]>: FromWasmAbi<Abi = WasmSlice>,
539{
540 type Abi = <Box<[T]> as FromWasmAbi>::Abi;
541
542 #[inline]
543 unsafe fn from_abi(js: Self::Abi) -> Self {
544 <Box<[T]>>::from_abi(js).into()
545 }
546
547 #[inline]
548 unsafe fn try_from_abi(js: Self::Abi) -> Result<Self, &'static str> {
549 <Box<[T]>>::try_from_abi(js).map(Into::into)
550 }
551}
552
553impl<T> OptionFromWasmAbi for Vec<T>
554where
555 Box<[T]>: FromWasmAbi<Abi = WasmSlice>,
556{
557 #[inline]
558 fn is_none(abi: &WasmSlice) -> bool {
559 abi.ptr.is_zero()
560 }
561}
562
563impl_nullable_from_shared_abi!(
564 is_null = |abi| is_js_null_slice(abi);
565 [T] Vec<T> where Box<[T]>: FromWasmAbi<Abi = WasmSlice>
566);
567
568impl IntoWasmAbi for String {
569 type Abi = <Vec<u8> as IntoWasmAbi>::Abi;
570
571 #[inline]
572 fn into_abi(self) -> Self::Abi {
573 unsafe_get_cached_str(&self).unwrap_or_else(|| self.into_bytes().into_abi())
576 }
577}
578
579impl OptionIntoWasmAbi for String {
580 #[inline]
581 fn none() -> Self::Abi {
582 null_slice()
583 }
584}
585
586impl_nullable_into_shared_abi!(null = js_null_slice(); [] String);
587
588impl FromWasmAbi for String {
589 type Abi = <Vec<u8> as FromWasmAbi>::Abi;
590
591 #[inline]
592 unsafe fn from_abi(js: Self::Abi) -> Self {
593 String::from_utf8_unchecked(<Vec<u8>>::from_abi(js))
594 }
595}
596
597impl OptionFromWasmAbi for String {
598 #[inline]
599 fn is_none(slice: &WasmSlice) -> bool {
600 slice.ptr.is_zero()
601 }
602}
603
604impl_nullable_from_shared_abi!(is_null = |slice| is_js_null_slice(slice); [] String);
605
606impl<'a> IntoWasmAbi for &'a str {
607 type Abi = <&'a [u8] as IntoWasmAbi>::Abi;
608
609 #[inline]
610 fn into_abi(self) -> Self::Abi {
611 unsafe_get_cached_str(self).unwrap_or_else(|| self.as_bytes().into_abi())
614 }
615}
616
617impl OptionIntoWasmAbi for &str {
618 #[inline]
619 fn none() -> Self::Abi {
620 null_slice()
621 }
622}
623
624impl_nullable_into_shared_abi!(null = js_null_slice(); [] &str);
625
626macro_rules! str_ref_into_wasm_abi {
628 ($($t:ty),* $(,)?) => ($(
629 impl IntoWasmAbi for &$t {
630 type Abi = <&'static str as IntoWasmAbi>::Abi;
631
632 #[inline]
633 fn into_abi(self) -> Self::Abi {
634 <&str as IntoWasmAbi>::into_abi(self)
635 }
636 }
637
638 impl OptionIntoWasmAbi for &$t {
639 #[inline]
640 fn none() -> Self::Abi {
641 <&str as OptionIntoWasmAbi>::none()
642 }
643 }
644
645 impl_nullable_into_shared_abi!(null = <&str as NullableIntoWasmAbi>::null(); [] &$t);
646 )*)
647}
648
649str_ref_into_wasm_abi!(String, Box<str>, Cow<'_, str>);
650
651impl RefFromWasmAbi for str {
652 type Abi = <[u8] as RefFromWasmAbi>::Abi;
653 type Anchor = Box<str>;
654
655 #[inline]
656 unsafe fn ref_from_abi(js: Self::Abi) -> Self::Anchor {
657 mem::transmute::<Box<[u8]>, Box<str>>(<Box<[u8]>>::from_abi(js))
658 }
659}
660
661impl LongRefFromWasmAbi for str {
662 type Abi = <[u8] as RefFromWasmAbi>::Abi;
663 type Anchor = Box<str>;
664
665 #[inline]
666 unsafe fn long_ref_from_abi(js: Self::Abi) -> Self::Anchor {
667 Self::ref_from_abi(js)
668 }
669}
670
671unsafe impl<'a> ErasableGeneric for &'a str {
672 type Repr = &'a str;
673}
674
675unsafe impl<T: ErasableGeneric> ErasableGeneric for Box<[T]> {
676 type Repr = Box<[T::Repr]>;
677}
678
679impl<'a> UpcastFrom<&'a str> for &'a str {}
680impl UpcastFrom<String> for String {}
681impl<'a, Target: UpcastFrom<&'a str>> UpcastFrom<&'a str> for Option<Target> {}
682impl<'a, Target: UpcastFrom<&'a str>> UpcastFrom<&'a str> for Nullable<Target> {}
683impl<Target: UpcastFrom<String>> UpcastFrom<String> for Option<Target> {}
684impl<Target: UpcastFrom<String>> UpcastFrom<String> for Nullable<Target> {}
685impl UpcastFrom<&str> for String {}
690impl UpcastFrom<String> for &str {}
691
692impl UpcastFrom<String> for JsValue {}
695impl UpcastFrom<String> for JsOption<JsValue> {}
696impl UpcastFrom<String> for JsNullable<JsValue> {}
697impl UpcastFrom<&str> for JsValue {}
698impl UpcastFrom<&str> for JsOption<JsValue> {}
699impl UpcastFrom<&str> for JsNullable<JsValue> {}
700
701impl<T, Target> UpcastFrom<Box<[T]>> for Box<[Target]> where Target: UpcastFrom<T> {}
702
703unsafe impl<T: ErasableGeneric> ErasableGeneric for Vec<T> {
704 type Repr = Vec<T::Repr>;
705}
706
707impl<T, Target> UpcastFrom<Vec<T>> for Vec<Target> where Target: UpcastFrom<T> {}
708
709impl<T: VectorIntoWasmAbi> IntoWasmAbi for Box<[T]> {
710 type Abi = <T as VectorIntoWasmAbi>::Abi;
711
712 fn into_abi(self) -> Self::Abi {
713 T::vector_into_abi(self)
714 }
715}
716
717impl<T> OptionIntoWasmAbi for Box<[T]>
718where
719 Self: IntoWasmAbi<Abi = WasmSlice>,
720{
721 fn none() -> WasmSlice {
722 null_slice()
723 }
724}
725
726impl_nullable_into_shared_abi!(
727 null = js_null_slice();
728 [T] Box<[T]> where Self: IntoWasmAbi<Abi = WasmSlice>
729);
730
731impl<T: VectorFromWasmAbi> FromWasmAbi for Box<[T]> {
732 type Abi = <T as VectorFromWasmAbi>::Abi;
733
734 unsafe fn from_abi(js: Self::Abi) -> Self {
735 T::vector_from_abi(js)
736 }
737
738 #[inline]
739 unsafe fn try_from_abi(js: Self::Abi) -> Result<Self, &'static str> {
740 T::try_vector_from_abi(js)
741 }
742}
743
744impl<T> OptionFromWasmAbi for Box<[T]>
745where
746 Self: FromWasmAbi<Abi = WasmSlice>,
747{
748 fn is_none(slice: &WasmSlice) -> bool {
749 slice.ptr.is_zero()
750 }
751}
752
753impl_nullable_from_shared_abi!(
754 is_null = |slice| is_js_null_slice(slice);
755 [T] Box<[T]> where Self: FromWasmAbi<Abi = WasmSlice>
756);
757
758impl<T: ErasableGeneric<Repr = JsValue> + WasmDescribe> VectorFromWasmAbi for T {
759 type Abi = WasmSlice;
760
761 #[inline]
762 unsafe fn vector_from_abi(js: WasmSlice) -> Box<[Self]> {
763 let ptr = js.ptr.into_usize() as *mut T;
764 let len = js.len.into_usize();
765 Vec::from_raw_parts(ptr, len, len).into_boxed_slice()
766 }
767}
768
769impl<T: ErasableGeneric<Repr = JsValue> + WasmDescribe> VectorIntoWasmAbi for T {
770 type Abi = WasmSlice;
771
772 #[inline]
773 fn vector_into_abi(vector: Box<[T]>) -> WasmSlice {
774 let ptr = vector.as_ptr();
775 let len = vector.len();
776 mem::forget(vector);
777 WasmSlice::from_usize(ptr as usize, len)
778 }
779}
780
781unsafe impl<'a, T: ErasableGeneric> ErasableGeneric for &'a [T]
782where
783 <T as ErasableGeneric>::Repr: 'a,
784{
785 type Repr = &'a [T::Repr];
786}
787
788impl<'a, T, Target> UpcastFrom<&'a [T]> for &'a [Target] where Target: UpcastFrom<T> {}
789
790macro_rules! ref_by_copy {
794 ($($t:ty => $base:ty,)*) => ($(
795 impl IntoWasmAbi for &$t {
796 type Abi = <$base as IntoWasmAbi>::Abi;
797
798 #[inline]
799 fn into_abi(self) -> Self::Abi {
800 (*self).into_abi()
801 }
802 }
803
804 impl MaybeIntoWasmAbi for &$t {
805 type MaybeAbi = <$base as MaybeIntoWasmAbi>::MaybeAbi;
806
807 #[inline]
808 fn into_maybe_abi(self) -> Self::MaybeAbi {
809 (*self).into_maybe_abi()
810 }
811
812 #[inline]
813 fn none() -> Self::MaybeAbi {
814 <$base as MaybeIntoWasmAbi>::none()
815 }
816 }
817
818 impl NullableIntoWasmAbi for &$t {
819 #[inline]
820 fn null() -> Self::MaybeAbi {
821 <$base as NullableIntoWasmAbi>::null()
822 }
823 }
824 )*)
825}
826
827ref_by_copy! {
828 u8 => u8, i8 => i8, u16 => u16, i16 => i16, u32 => u32, i32 => i32,
829 u64 => u64, i64 => i64, u128 => u128, i128 => i128, usize => usize,
830 isize => isize, f32 => f32, f64 => f64, bool => bool, char => char,
831 &str => &'static str, &String => &'static String,
832 &Box<str> => &'static Box<str>, &Cow<'_, str> => &'static Cow<'static, str>,
833}
834
835impl<'a, T: WasmDescribe> IntoWasmAbi for &'a Option<T>
836where
837 Option<&'a T>: IntoWasmAbi,
838{
839 type Abi = <Option<&'a T> as IntoWasmAbi>::Abi;
840
841 #[inline]
842 fn into_abi(self) -> Self::Abi {
843 self.as_ref().into_abi()
844 }
845}
846
847impl<'a, T: WasmDescribe> IntoWasmAbi for &'a Nullable<T>
848where
849 Nullable<&'a T>: IntoWasmAbi,
850{
851 type Abi = <Nullable<&'a T> as IntoWasmAbi>::Abi;
852
853 #[inline]
854 fn into_abi(self) -> Self::Abi {
855 self.as_ref().into_abi()
856 }
857}
858
859impl<'a, T: WasmDescribe> OptionIntoWasmAbi for &'a Nullable<T>
860where
861 Nullable<&'a T>: OptionIntoWasmAbi,
862{
863 #[inline]
864 fn none() -> Self::Abi {
865 <Nullable<&'a T> as OptionIntoWasmAbi>::none()
866 }
867}