1use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
2use crate::describe::inform;
3use crate::JsValue;
4#[cfg(all(target_family = "wasm", feature = "std", panic = "unwind"))]
5use core::any::Any;
6use core::borrow::{Borrow, BorrowMut};
7#[cfg(target_feature = "atomics")]
8use core::cell::UnsafeCell;
9use core::cell::{Cell, RefCell};
10use core::convert::Infallible;
11use core::marker::PhantomData;
12use core::ops::{Deref, DerefMut};
13use core::panic::{RefUnwindSafe, UnwindSafe};
14#[cfg(target_feature = "atomics")]
15use core::sync::atomic::{AtomicU8, Ordering};
16use wasm_bindgen_shared::tys::FUNCTION;
17
18use alloc::alloc::{alloc, dealloc, realloc, Layout};
19use alloc::rc::Rc;
20use once_cell::unsync::Lazy;
21
22pub extern crate alloc;
23pub extern crate core;
24#[cfg(feature = "std")]
25pub extern crate std;
26
27pub mod marker;
28
29pub use wasm_bindgen_macro::BindgenedStruct;
30
31pub fn js_panic(err: JsValue) {
33 #[cfg(all(feature = "std", not(target_feature = "atomics")))]
34 ::std::panic::panic_any(err);
35 #[cfg(not(all(feature = "std", not(target_feature = "atomics"))))]
36 ::core::panic!("{:?}", err);
37}
38
39pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
45 #[inline(never)]
84 #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
85 unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
86 prim1: <From::Abi as WasmAbi>::Prim1,
87 prim2: <From::Abi as WasmAbi>::Prim2,
88 prim3: <From::Abi as WasmAbi>::Prim3,
89 prim4: <From::Abi as WasmAbi>::Prim4,
90 ) -> WasmRet<To::Abi> {
91 inform(FUNCTION);
92 inform(0);
93 inform(1);
94 From::describe();
95 To::describe();
96 To::describe();
97 core::ptr::read(super::__wbindgen_describe_cast(
100 breaks_if_inlined::<From, To> as _,
101 &(prim1, prim2, prim3, prim4) as *const _ as _,
102 ) as _)
103 }
104
105 let (prim1, prim2, prim3, prim4) = value.into_abi().split();
106
107 unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
108}
109
110pub(crate) const JSIDX_OFFSET: u32 = 1024; pub(crate) const JSIDX_UNDEFINED: u32 = JSIDX_OFFSET;
112pub(crate) const JSIDX_NULL: u32 = JSIDX_OFFSET + 1;
113pub(crate) const JSIDX_TRUE: u32 = JSIDX_OFFSET + 2;
114pub(crate) const JSIDX_FALSE: u32 = JSIDX_OFFSET + 3;
115pub(crate) const JSIDX_RESERVED: u32 = JSIDX_OFFSET + 4;
116
117pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
118
119#[cfg(not(target_feature = "atomics"))]
120unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
121
122#[cfg(not(target_feature = "atomics"))]
123unsafe impl<T> Send for ThreadLocalWrapper<T> {}
124
125pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
127
128impl<T, F> LazyCell<T, F> {
129 pub const fn new(init: F) -> LazyCell<T, F> {
130 Self(ThreadLocalWrapper(Lazy::new(init)))
131 }
132}
133
134impl<T, F: FnOnce() -> T> LazyCell<T, F> {
135 pub fn force(this: &Self) -> &T {
136 &this.0 .0
137 }
138}
139
140impl<T> Deref for LazyCell<T> {
141 type Target = T;
142
143 fn deref(&self) -> &T {
144 ::once_cell::unsync::Lazy::force(&self.0 .0)
145 }
146}
147
148#[cfg(not(target_feature = "atomics"))]
149pub use LazyCell as LazyLock;
150
151#[cfg(target_feature = "atomics")]
152pub struct LazyLock<T, F = fn() -> T> {
153 state: AtomicU8,
154 data: UnsafeCell<Data<T, F>>,
155}
156
157#[cfg(target_feature = "atomics")]
158enum Data<T, F> {
159 Value(T),
160 Init(F),
161}
162
163#[cfg(target_feature = "atomics")]
164impl<T, F> LazyLock<T, F> {
165 const STATE_UNINIT: u8 = 0;
166 const STATE_INITIALIZING: u8 = 1;
167 const STATE_INIT: u8 = 2;
168
169 pub const fn new(init: F) -> LazyLock<T, F> {
170 Self {
171 state: AtomicU8::new(Self::STATE_UNINIT),
172 data: UnsafeCell::new(Data::Init(init)),
173 }
174 }
175}
176
177#[cfg(target_feature = "atomics")]
178impl<T> Deref for LazyLock<T> {
179 type Target = T;
180
181 fn deref(&self) -> &T {
182 let mut state = self.state.load(Ordering::Acquire);
183
184 loop {
185 match state {
186 Self::STATE_INIT => {
187 let Data::Value(value) = (unsafe { &*self.data.get() }) else {
188 unreachable!()
189 };
190 return value;
191 }
192 Self::STATE_UNINIT => {
193 if let Err(new_state) = self.state.compare_exchange_weak(
194 Self::STATE_UNINIT,
195 Self::STATE_INITIALIZING,
196 Ordering::Acquire,
197 Ordering::Relaxed,
198 ) {
199 state = new_state;
200 continue;
201 }
202
203 let data = unsafe { &mut *self.data.get() };
204 let Data::Init(init) = data else {
205 unreachable!()
206 };
207 *data = Data::Value(init());
208 self.state.store(Self::STATE_INIT, Ordering::Release);
209 state = Self::STATE_INIT;
210 }
211 Self::STATE_INITIALIZING => {
212 state = self.state.load(Ordering::Acquire);
215 }
216 _ => unreachable!(),
217 }
218 }
219 }
220}
221
222#[cfg(target_feature = "atomics")]
223unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
224
225#[cfg(target_feature = "atomics")]
226unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
227
228#[macro_export]
229#[doc(hidden)]
230#[cfg(not(target_feature = "atomics"))]
231macro_rules! __wbindgen_thread_local {
232 ($wasm_bindgen:tt, $actual_ty:ty) => {{
233 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
234 $wasm_bindgen::__rt::LazyCell::new(init);
235 $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
236 }};
237}
238
239#[macro_export]
240#[doc(hidden)]
241#[cfg(target_feature = "atomics")]
242#[allow_internal_unstable(thread_local)]
243macro_rules! __wbindgen_thread_local {
244 ($wasm_bindgen:tt, $actual_ty:ty) => {{
245 #[thread_local]
246 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
247 $wasm_bindgen::__rt::LazyCell::new(init);
248 $wasm_bindgen::JsThreadLocal {
249 __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
250 }
251 }};
252}
253
254#[macro_export]
255#[doc(hidden)]
256#[cfg(not(wasm_bindgen_unstable_test_coverage))]
257macro_rules! __wbindgen_coverage {
258 ($item:item) => {
259 $item
260 };
261}
262
263#[macro_export]
264#[doc(hidden)]
265#[cfg(wasm_bindgen_unstable_test_coverage)]
266#[allow_internal_unstable(coverage_attribute)]
267macro_rules! __wbindgen_coverage {
268 ($item:item) => {
269 #[coverage(off)]
270 $item
271 };
272}
273
274#[inline]
275pub fn assert_not_null<T>(s: *mut T) {
276 if s.is_null() {
277 throw_null();
278 }
279}
280
281#[cfg(target_arch = "wasm64")]
282pub type WasmWordRepr = f64;
283#[cfg(not(target_arch = "wasm64"))]
284pub type WasmWordRepr = u32;
285
286#[cfg(target_arch = "wasm64")]
289pub type WasmSignedWordRepr = f64;
290#[cfg(not(target_arch = "wasm64"))]
291pub type WasmSignedWordRepr = i32;
292
293#[repr(transparent)]
295#[derive(Copy, Clone, Default)]
296pub struct WasmWord(WasmWordRepr);
297
298impl WasmWord {
299 #[inline]
300 pub fn from_usize(value: usize) -> Self {
301 #[cfg(target_arch = "wasm64")]
302 {
303 Self(value as f64)
304 }
305 #[cfg(not(target_arch = "wasm64"))]
306 {
307 Self(value as u32)
308 }
309 }
310
311 #[inline]
312 pub fn into_usize(self) -> usize {
313 self.0 as usize
314 }
315
316 #[inline]
317 pub fn from_isize(value: isize) -> Self {
318 #[cfg(target_arch = "wasm64")]
319 {
320 Self(value as f64)
321 }
322 #[cfg(not(target_arch = "wasm64"))]
323 {
324 Self(value as u32)
325 }
326 }
327
328 #[inline]
329 pub fn into_isize(self) -> isize {
330 self.0 as isize
331 }
332
333 #[inline]
334 pub fn is_zero(&self) -> bool {
335 #[cfg(target_arch = "wasm64")]
336 {
337 self.0 == 0.0
338 }
339 #[cfg(not(target_arch = "wasm64"))]
340 {
341 self.0 == 0
342 }
343 }
344}
345
346impl WasmAbi for WasmWord {
347 type Prim1 = WasmWordRepr;
348 type Prim2 = ();
349 type Prim3 = ();
350 type Prim4 = ();
351
352 #[inline]
353 fn split(self) -> (Self::Prim1, (), (), ()) {
354 (self.0, (), (), ())
355 }
356
357 #[inline]
358 fn join(prim1: Self::Prim1, _: (), _: (), _: ()) -> Self {
359 Self(prim1)
360 }
361}
362
363#[repr(transparent)]
365#[derive(Copy, Clone)]
366pub struct WasmPtr<T> {
367 word: WasmWord,
368 _marker: PhantomData<*mut T>,
369}
370
371impl<T> Default for WasmPtr<T> {
372 #[inline]
373 fn default() -> Self {
374 Self::null()
375 }
376}
377
378impl<T> WasmPtr<T> {
379 #[inline]
380 pub fn from_ptr(ptr: *mut T) -> Self {
381 Self::from_usize(ptr as usize)
382 }
383
384 #[inline]
385 pub fn into_ptr(self) -> *mut T {
386 self.into_usize() as *mut T
387 }
388
389 #[inline]
390 pub fn from_usize(value: usize) -> Self {
391 Self {
392 word: WasmWord::from_usize(value),
393 _marker: PhantomData,
394 }
395 }
396
397 #[inline]
398 pub fn into_usize(self) -> usize {
399 self.word.into_usize()
400 }
401
402 #[inline]
403 pub fn null() -> Self {
404 Self::from_usize(0)
405 }
406
407 #[inline]
408 pub fn is_null(&self) -> bool {
409 self.word.is_zero()
410 }
411}
412
413impl<T> WasmAbi for WasmPtr<T> {
414 type Prim1 = <WasmWord as WasmAbi>::Prim1;
415 type Prim2 = ();
416 type Prim3 = ();
417 type Prim4 = ();
418
419 #[inline]
420 fn split(self) -> (Self::Prim1, (), (), ()) {
421 self.word.split()
422 }
423
424 #[inline]
425 fn join(prim1: Self::Prim1, _: (), _: (), _: ()) -> Self {
426 Self {
427 word: WasmWord::join(prim1, (), (), ()),
428 _marker: PhantomData,
429 }
430 }
431}
432
433#[cfg(all(test, target_arch = "wasm64"))]
437mod tests {
438 use super::WasmWord;
439
440 #[test]
441 fn wasm_word_roundtrips_large_pointer_values() {
442 let value = 1usize << 60;
443 assert_eq!(WasmWord::from_usize(value).into_usize(), value);
444
445 let signed = -(1isize << 40);
446 assert_eq!(WasmWord::from_isize(signed).into_isize(), signed);
447 }
448}
449
450#[cold]
451#[inline(never)]
452fn throw_null() -> ! {
453 super::throw_str("null pointer passed to rust");
454}
455
456pub struct WasmRefCell<T: ?Sized> {
474 inner: RefCell<T>,
475}
476
477impl<T: ?Sized> UnwindSafe for WasmRefCell<T> {}
478impl<T: ?Sized> RefUnwindSafe for WasmRefCell<T> {}
479
480impl<T: ?Sized> WasmRefCell<T> {
481 pub fn new(value: T) -> WasmRefCell<T>
482 where
483 T: Sized,
484 {
485 WasmRefCell {
486 inner: RefCell::new(value),
487 }
488 }
489
490 pub fn get_mut(&mut self) -> &mut T {
491 self.inner.get_mut()
492 }
493
494 pub fn borrow(&self) -> Ref<'_, T> {
495 match self.inner.try_borrow() {
496 Ok(inner) => Ref { inner },
497 Err(_) => borrow_fail(),
498 }
499 }
500
501 pub fn borrow_mut(&self) -> RefMut<'_, T> {
502 match self.inner.try_borrow_mut() {
503 Ok(inner) => RefMut { inner },
504 Err(_) => borrow_fail(),
505 }
506 }
507
508 pub fn into_inner(self) -> T
509 where
510 T: Sized,
511 {
512 self.inner.into_inner()
513 }
514}
515
516pub struct Ref<'b, T: ?Sized + 'b> {
517 inner: core::cell::Ref<'b, T>,
518}
519
520impl<T: ?Sized> Deref for Ref<'_, T> {
521 type Target = T;
522
523 #[inline]
524 fn deref(&self) -> &T {
525 &self.inner
526 }
527}
528
529impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
530 #[inline]
531 fn borrow(&self) -> &T {
532 self
533 }
534}
535
536pub struct RefMut<'b, T: ?Sized + 'b> {
537 inner: core::cell::RefMut<'b, T>,
538}
539
540impl<T: ?Sized> Deref for RefMut<'_, T> {
541 type Target = T;
542
543 #[inline]
544 fn deref(&self) -> &T {
545 &self.inner
546 }
547}
548
549impl<T: ?Sized> DerefMut for RefMut<'_, T> {
550 #[inline]
551 fn deref_mut(&mut self) -> &mut T {
552 &mut self.inner
553 }
554}
555
556impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
557 #[inline]
558 fn borrow(&self) -> &T {
559 self
560 }
561}
562
563impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
564 #[inline]
565 fn borrow_mut(&mut self) -> &mut T {
566 self
567 }
568}
569
570#[cfg(panic = "unwind")]
571fn borrow_fail() -> ! {
572 panic!(
573 "recursive use of an object detected which would lead to \
574 unsafe aliasing in rust",
575 )
576}
577
578#[cfg(not(panic = "unwind"))]
579fn borrow_fail() -> ! {
580 super::throw_str(
581 "recursive use of an object detected which would lead to \
582 unsafe aliasing in rust",
583 );
584}
585
586pub struct RcRef<T: ?Sized + 'static> {
592 ref_: Ref<'static, T>,
601 _rc: Rc<WasmRefCell<T>>,
602}
603
604impl<T: ?Sized> UnwindSafe for RcRef<T> {}
605
606impl<T: ?Sized> RcRef<T> {
607 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
608 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
609 Self { _rc: rc, ref_ }
610 }
611}
612
613impl<T: ?Sized> Deref for RcRef<T> {
614 type Target = T;
615
616 #[inline]
617 fn deref(&self) -> &T {
618 &self.ref_
619 }
620}
621
622impl<T: ?Sized> Borrow<T> for RcRef<T> {
623 #[inline]
624 fn borrow(&self) -> &T {
625 &self.ref_
626 }
627}
628
629pub struct RcRefMut<T: ?Sized + 'static> {
635 ref_: RefMut<'static, T>,
636 _rc: Rc<WasmRefCell<T>>,
637}
638
639impl<T: ?Sized> RcRefMut<T> {
640 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
641 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
642 Self { _rc: rc, ref_ }
643 }
644}
645
646impl<T: ?Sized> Deref for RcRefMut<T> {
647 type Target = T;
648
649 #[inline]
650 fn deref(&self) -> &T {
651 &self.ref_
652 }
653}
654
655impl<T: ?Sized> DerefMut for RcRefMut<T> {
656 #[inline]
657 fn deref_mut(&mut self) -> &mut T {
658 &mut self.ref_
659 }
660}
661
662impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
663 #[inline]
664 fn borrow(&self) -> &T {
665 &self.ref_
666 }
667}
668
669impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
670 #[inline]
671 fn borrow_mut(&mut self) -> &mut T {
672 &mut self.ref_
673 }
674}
675
676#[no_mangle]
677pub extern "C" fn __wbindgen_malloc(size: WasmWord, align: WasmWord) -> WasmPtr<u8> {
678 let size = size.into_usize();
679 let align = align.into_usize();
680 if let Ok(layout) = Layout::from_size_align(size, align) {
681 unsafe {
682 if layout.size() > 0 {
683 let ptr = alloc(layout);
684 if !ptr.is_null() {
685 return WasmPtr::from_ptr(ptr);
686 }
687 } else {
688 return WasmPtr::from_usize(align);
689 }
690 }
691 }
692
693 malloc_failure();
694}
695
696#[no_mangle]
697pub unsafe extern "C" fn __wbindgen_realloc(
698 ptr: WasmPtr<u8>,
699 old_size: WasmWord,
700 new_size: WasmWord,
701 align: WasmWord,
702) -> WasmPtr<u8> {
703 let ptr = ptr.into_ptr();
704 let old_size = old_size.into_usize();
705 let new_size = new_size.into_usize();
706 let align = align.into_usize();
707 debug_assert!(old_size > 0);
708 debug_assert!(new_size > 0);
709 if let Ok(layout) = Layout::from_size_align(old_size, align) {
710 let ptr = realloc(ptr, layout, new_size);
711 if !ptr.is_null() {
712 return WasmPtr::from_ptr(ptr);
713 }
714 }
715 malloc_failure();
716}
717
718#[cold]
719fn malloc_failure() -> ! {
720 cfg_if::cfg_if! {
721 if #[cfg(debug_assertions)] {
722 super::throw_str("invalid malloc request")
723 } else if #[cfg(feature = "std")] {
724 std::process::abort();
725 } else if #[cfg(target_arch = "wasm32")] {
726 core::arch::wasm32::unreachable();
728 } else if #[cfg(target_arch = "wasm64")] {
729 core::arch::wasm64::unreachable();
731 } else {
732 unreachable!()
733 }
734 }
735}
736
737#[no_mangle]
738pub unsafe extern "C" fn __wbindgen_free(ptr: WasmPtr<u8>, size: WasmWord, align: WasmWord) {
739 let size = size.into_usize();
740 if size == 0 {
743 return;
744 }
745 let ptr = ptr.into_ptr();
746 let align = align.into_usize();
747 let layout = Layout::from_size_align_unchecked(size, align);
748 dealloc(ptr, layout);
749}
750
751#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
785pub fn link_mem_intrinsics() {
786 crate::link::link_intrinsics();
787}
788
789#[cfg_attr(target_feature = "atomics", thread_local)]
790static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
791
792#[cfg(panic = "unwind")]
793#[no_mangle]
794pub static mut __instance_terminated: u32 = 0;
795
796#[cfg(panic = "unwind")]
799#[no_mangle]
800pub static mut __abort_handler: u32 = 0;
801
802#[cfg(panic = "unwind")]
816pub fn set_on_abort(f: fn()) -> Option<fn()> {
817 unsafe {
821 let prev = __abort_handler;
822 __abort_handler = f as usize as u32;
823 if prev != 0 {
824 Some(core::mem::transmute::<usize, fn()>(prev as usize))
825 } else {
826 None
827 }
828 }
829}
830
831#[cfg(not(panic = "unwind"))]
833pub fn set_on_abort(_f: fn()) -> Option<fn()> {
834 None
835}
836
837pub fn schedule_reinit() {
842 crate::__wbindgen_reinit();
843}
844
845#[no_mangle]
846pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
847 debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
848 GLOBAL_EXNDATA.0.set([1, idx]);
849}
850
851pub fn take_last_exception() -> Result<(), super::JsValue> {
852 let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
853 Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
854 } else {
855 Ok(())
856 };
857 GLOBAL_EXNDATA.0.set([0, 0]);
858 ret
859}
860
861pub trait IntoJsResult {
866 fn into_js_result(self) -> Result<JsValue, JsValue>;
867}
868
869impl IntoJsResult for () {
870 fn into_js_result(self) -> Result<JsValue, JsValue> {
871 Ok(JsValue::undefined())
872 }
873}
874
875impl<T: Into<JsValue>> IntoJsResult for T {
876 fn into_js_result(self) -> Result<JsValue, JsValue> {
877 Ok(self.into())
878 }
879}
880
881impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
882 fn into_js_result(self) -> Result<JsValue, JsValue> {
883 match self {
884 Ok(e) => Ok(e.into()),
885 Err(e) => Err(e.into()),
886 }
887 }
888}
889
890impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
891 fn into_js_result(self) -> Result<JsValue, JsValue> {
892 match self {
893 Ok(()) => Ok(JsValue::undefined()),
894 Err(e) => Err(e.into()),
895 }
896 }
897}
898
899pub trait Start {
902 fn start(self);
903}
904
905impl Start for () {
906 #[inline]
907 fn start(self) {}
908}
909
910impl<E: Into<JsValue>> Start for Result<(), E> {
911 #[inline]
912 fn start(self) {
913 if let Err(e) = self {
914 crate::throw_val(e.into());
915 }
916 }
917}
918
919pub struct MainWrapper<T>(pub Option<T>);
922
923pub trait Main {
924 fn __wasm_bindgen_main(&mut self);
925}
926
927impl Main for &mut &mut MainWrapper<()> {
928 #[inline]
929 fn __wasm_bindgen_main(&mut self) {}
930}
931
932impl Main for &mut &mut MainWrapper<Infallible> {
933 #[inline]
934 fn __wasm_bindgen_main(&mut self) {}
935}
936
937impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
938 #[inline]
939 fn __wasm_bindgen_main(&mut self) {
940 if let Err(e) = self.0.take().unwrap() {
941 crate::throw_val(e.into());
942 }
943 }
944}
945
946impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
947 #[inline]
948 fn __wasm_bindgen_main(&mut self) {
949 if let Err(e) = self.0.take().unwrap() {
950 crate::throw_str(&alloc::format!("{e:?}"));
951 }
952 }
953}
954
955pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
956 let mut len = 0;
957 let mut i = 0;
958 while i < slices.len() {
959 len += slices[i].len();
960 i += 1;
961 }
962 len
963}
964
965pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
966 slices: [&[u8]; SIZE],
967) -> [u8; RESULT_LEN] {
968 let mut result = [0; RESULT_LEN];
969
970 let mut slice_index = 0;
971 let mut result_offset = 0;
972
973 while slice_index < slices.len() {
974 let mut i = 0;
975 let slice = slices[slice_index];
976 while i < slice.len() {
977 result[result_offset] = slice[i];
978 i += 1;
979 result_offset += 1;
980 }
981 slice_index += 1;
982 }
983
984 result
985}
986
987pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
991 let mut result: [u8; 5] = [0; 5];
992 let mut i = 0;
993 while i < 4 {
994 result[i] = ((value >> (7 * i)) | 0x80) as u8;
995 i += 1;
996 }
997 result[4] = (value >> (7 * 4)) as u8;
998 result
999}
1000
1001#[cfg(all(target_family = "wasm", feature = "std", panic = "unwind"))]
1002#[wasm_bindgen_macro::wasm_bindgen(wasm_bindgen = crate, raw_module = "__wbindgen_placeholder__")]
1003extern "C" {
1004 fn __wbindgen_panic_error(msg: &JsValue) -> JsValue;
1005}
1006
1007#[cfg(all(target_family = "wasm", feature = "std", panic = "unwind"))]
1008pub fn panic_to_panic_error(val: std::boxed::Box<dyn Any + Send>) -> JsValue {
1009 #[cfg(not(target_feature = "atomics"))]
1010 {
1011 if let Some(s) = val.downcast_ref::<JsValue>() {
1012 return __wbindgen_panic_error(&s);
1013 }
1014 }
1015 let maybe_panic_msg: Option<&str> = if let Some(s) = val.downcast_ref::<&str>() {
1016 Some(s)
1017 } else if let Some(s) = val.downcast_ref::<std::string::String>() {
1018 Some(s)
1019 } else {
1020 None
1021 };
1022 let err: JsValue = __wbindgen_panic_error(&JsValue::from_str(
1023 maybe_panic_msg.unwrap_or("No panic message available"),
1024 ));
1025 err
1026}
1027
1028#[cfg(all(target_family = "wasm", feature = "std", panic = "unwind"))]
1029pub fn maybe_catch_unwind<F: FnOnce() -> R + std::panic::UnwindSafe, R>(f: F) -> R {
1030 let result = std::panic::catch_unwind(f);
1031 match result {
1032 Ok(val) => val,
1033 Err(e) => {
1034 crate::throw_val(panic_to_panic_error(e));
1035 }
1036 }
1037}
1038
1039#[cfg(not(all(target_family = "wasm", feature = "std", panic = "unwind")))]
1040pub fn maybe_catch_unwind<F: FnOnce() -> R, R>(f: F) -> R {
1041 f()
1042}