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