1use crate::JsValue;
2use core::borrow::{Borrow, BorrowMut};
3use core::cell::{Cell, UnsafeCell};
4use core::convert::Infallible;
5use core::mem;
6use core::ops::{Deref, DerefMut};
7#[cfg(target_feature = "atomics")]
8use core::sync::atomic::{AtomicU8, Ordering};
9
10use alloc::alloc::{alloc, dealloc, realloc, Layout};
11use alloc::boxed::Box;
12use alloc::rc::Rc;
13use once_cell::unsync::Lazy;
14
15pub extern crate alloc;
16pub extern crate core;
17#[cfg(feature = "std")]
18pub extern crate std;
19
20pub mod marker;
21
22pub use wasm_bindgen_macro::BindgenedStruct;
23
24pub struct LazyCell<T, F = fn() -> T>(Wrapper<Lazy<T, F>>);
26
27struct Wrapper<T>(T);
28
29unsafe impl<T> Sync for Wrapper<T> {}
30
31unsafe impl<T> Send for Wrapper<T> {}
32
33impl<T, F> LazyCell<T, F> {
34 pub const fn new(init: F) -> LazyCell<T, F> {
35 Self(Wrapper(Lazy::new(init)))
36 }
37}
38
39impl<T, F: FnOnce() -> T> LazyCell<T, F> {
40 pub(crate) fn try_with<R>(
41 &self,
42 f: impl FnOnce(&T) -> R,
43 ) -> Result<R, core::convert::Infallible> {
44 Ok(f(&self.0 .0))
45 }
46
47 pub fn force(this: &Self) -> &T {
48 &this.0 .0
49 }
50}
51
52impl<T> Deref for LazyCell<T> {
53 type Target = T;
54
55 fn deref(&self) -> &T {
56 ::once_cell::unsync::Lazy::force(&self.0 .0)
57 }
58}
59
60#[cfg(not(target_feature = "atomics"))]
61pub use LazyCell as LazyLock;
62
63#[cfg(target_feature = "atomics")]
64pub struct LazyLock<T, F = fn() -> T> {
65 state: AtomicU8,
66 data: Wrapper<UnsafeCell<Data<T, F>>>,
67}
68
69#[cfg(target_feature = "atomics")]
70enum Data<T, F> {
71 Value(T),
72 Init(F),
73}
74
75#[cfg(target_feature = "atomics")]
76impl<T, F> LazyLock<T, F> {
77 const STATE_UNINIT: u8 = 0;
78 const STATE_INITIALIZING: u8 = 1;
79 const STATE_INIT: u8 = 2;
80
81 pub const fn new(init: F) -> LazyLock<T, F> {
82 Self {
83 state: AtomicU8::new(Self::STATE_UNINIT),
84 data: Wrapper(UnsafeCell::new(Data::Init(init))),
85 }
86 }
87}
88
89#[cfg(target_feature = "atomics")]
90impl<T> Deref for LazyLock<T> {
91 type Target = T;
92
93 fn deref(&self) -> &T {
94 let mut state = self.state.load(Ordering::Acquire);
95
96 loop {
97 match state {
98 Self::STATE_INIT => {
99 let Data::Value(value) = (unsafe { &*self.data.0.get() }) else {
100 unreachable!()
101 };
102 return value;
103 }
104 Self::STATE_UNINIT => {
105 if let Err(new_state) = self.state.compare_exchange_weak(
106 Self::STATE_UNINIT,
107 Self::STATE_INITIALIZING,
108 Ordering::Acquire,
109 Ordering::Relaxed,
110 ) {
111 state = new_state;
112 continue;
113 }
114
115 let data = unsafe { &mut *self.data.0.get() };
116 let Data::Init(init) = data else {
117 unreachable!()
118 };
119 *data = Data::Value(init());
120 self.state.store(Self::STATE_INIT, Ordering::Release);
121 state = Self::STATE_INIT;
122 }
123 Self::STATE_INITIALIZING => {
124 state = self.state.load(Ordering::Acquire);
127 }
128 _ => unreachable!(),
129 }
130 }
131 }
132}
133
134#[macro_export]
135#[doc(hidden)]
136#[cfg(not(target_feature = "atomics"))]
137macro_rules! __wbindgen_thread_local {
138 ($wasm_bindgen:tt, $actual_ty:ty) => {{
139 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
140 $wasm_bindgen::__rt::LazyCell::new(init);
141 $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
142 }};
143}
144
145#[macro_export]
146#[doc(hidden)]
147#[cfg(target_feature = "atomics")]
148#[allow_internal_unstable(thread_local)]
149macro_rules! __wbindgen_thread_local {
150 ($wasm_bindgen:tt, $actual_ty:ty) => {{
151 #[thread_local]
152 static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
153 $wasm_bindgen::__rt::LazyCell::new(init);
154 $wasm_bindgen::JsThreadLocal {
155 __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
156 }
157 }};
158}
159
160#[macro_export]
161#[doc(hidden)]
162#[cfg(not(wasm_bindgen_unstable_test_coverage))]
163macro_rules! __wbindgen_coverage {
164 ($item:item) => {
165 $item
166 };
167}
168
169#[macro_export]
170#[doc(hidden)]
171#[cfg(wasm_bindgen_unstable_test_coverage)]
172#[allow_internal_unstable(coverage_attribute)]
173macro_rules! __wbindgen_coverage {
174 ($item:item) => {
175 #[coverage(off)]
176 $item
177 };
178}
179
180#[inline]
181pub fn assert_not_null<T>(s: *mut T) {
182 if s.is_null() {
183 throw_null();
184 }
185}
186
187#[cold]
188#[inline(never)]
189fn throw_null() -> ! {
190 super::throw_str("null pointer passed to rust");
191}
192
193pub struct WasmRefCell<T: ?Sized> {
211 borrow: Cell<usize>,
212 value: UnsafeCell<T>,
213}
214
215impl<T: ?Sized> WasmRefCell<T> {
216 pub fn new(value: T) -> WasmRefCell<T>
217 where
218 T: Sized,
219 {
220 WasmRefCell {
221 value: UnsafeCell::new(value),
222 borrow: Cell::new(0),
223 }
224 }
225
226 pub fn get_mut(&mut self) -> &mut T {
227 unsafe { &mut *self.value.get() }
228 }
229
230 pub fn borrow(&self) -> Ref<T> {
231 unsafe {
232 if self.borrow.get() == usize::MAX {
233 borrow_fail();
234 }
235 self.borrow.set(self.borrow.get() + 1);
236 Ref {
237 value: &*self.value.get(),
238 borrow: &self.borrow,
239 }
240 }
241 }
242
243 pub fn borrow_mut(&self) -> RefMut<T> {
244 unsafe {
245 if self.borrow.get() != 0 {
246 borrow_fail();
247 }
248 self.borrow.set(usize::MAX);
249 RefMut {
250 value: &mut *self.value.get(),
251 borrow: &self.borrow,
252 }
253 }
254 }
255
256 pub fn into_inner(self) -> T
257 where
258 T: Sized,
259 {
260 self.value.into_inner()
261 }
262}
263
264pub struct Ref<'b, T: ?Sized + 'b> {
265 value: &'b T,
266 borrow: &'b Cell<usize>,
267}
268
269impl<T: ?Sized> Deref for Ref<'_, T> {
270 type Target = T;
271
272 #[inline]
273 fn deref(&self) -> &T {
274 self.value
275 }
276}
277
278impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
279 #[inline]
280 fn borrow(&self) -> &T {
281 self.value
282 }
283}
284
285impl<T: ?Sized> Drop for Ref<'_, T> {
286 fn drop(&mut self) {
287 self.borrow.set(self.borrow.get() - 1);
288 }
289}
290
291pub struct RefMut<'b, T: ?Sized + 'b> {
292 value: &'b mut T,
293 borrow: &'b Cell<usize>,
294}
295
296impl<T: ?Sized> Deref for RefMut<'_, T> {
297 type Target = T;
298
299 #[inline]
300 fn deref(&self) -> &T {
301 self.value
302 }
303}
304
305impl<T: ?Sized> DerefMut for RefMut<'_, T> {
306 #[inline]
307 fn deref_mut(&mut self) -> &mut T {
308 self.value
309 }
310}
311
312impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
313 #[inline]
314 fn borrow(&self) -> &T {
315 self.value
316 }
317}
318
319impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
320 #[inline]
321 fn borrow_mut(&mut self) -> &mut T {
322 self.value
323 }
324}
325
326impl<T: ?Sized> Drop for RefMut<'_, T> {
327 fn drop(&mut self) {
328 self.borrow.set(0);
329 }
330}
331
332fn borrow_fail() -> ! {
333 super::throw_str(
334 "recursive use of an object detected which would lead to \
335 unsafe aliasing in rust",
336 );
337}
338
339pub struct RcRef<T: ?Sized + 'static> {
345 ref_: Ref<'static, T>,
354 _rc: Rc<WasmRefCell<T>>,
355}
356
357impl<T: ?Sized> RcRef<T> {
358 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
359 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
360 Self { _rc: rc, ref_ }
361 }
362}
363
364impl<T: ?Sized> Deref for RcRef<T> {
365 type Target = T;
366
367 #[inline]
368 fn deref(&self) -> &T {
369 &self.ref_
370 }
371}
372
373impl<T: ?Sized> Borrow<T> for RcRef<T> {
374 #[inline]
375 fn borrow(&self) -> &T {
376 &self.ref_
377 }
378}
379
380pub struct RcRefMut<T: ?Sized + 'static> {
386 ref_: RefMut<'static, T>,
387 _rc: Rc<WasmRefCell<T>>,
388}
389
390impl<T: ?Sized> RcRefMut<T> {
391 pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
392 let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
393 Self { _rc: rc, ref_ }
394 }
395}
396
397impl<T: ?Sized> Deref for RcRefMut<T> {
398 type Target = T;
399
400 #[inline]
401 fn deref(&self) -> &T {
402 &self.ref_
403 }
404}
405
406impl<T: ?Sized> DerefMut for RcRefMut<T> {
407 #[inline]
408 fn deref_mut(&mut self) -> &mut T {
409 &mut self.ref_
410 }
411}
412
413impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
414 #[inline]
415 fn borrow(&self) -> &T {
416 &self.ref_
417 }
418}
419
420impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
421 #[inline]
422 fn borrow_mut(&mut self) -> &mut T {
423 &mut self.ref_
424 }
425}
426
427#[no_mangle]
428pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
429 if let Ok(layout) = Layout::from_size_align(size, align) {
430 unsafe {
431 if layout.size() > 0 {
432 let ptr = alloc(layout);
433 if !ptr.is_null() {
434 return ptr;
435 }
436 } else {
437 return align as *mut u8;
438 }
439 }
440 }
441
442 malloc_failure();
443}
444
445#[no_mangle]
446pub unsafe extern "C" fn __wbindgen_realloc(
447 ptr: *mut u8,
448 old_size: usize,
449 new_size: usize,
450 align: usize,
451) -> *mut u8 {
452 debug_assert!(old_size > 0);
453 debug_assert!(new_size > 0);
454 if let Ok(layout) = Layout::from_size_align(old_size, align) {
455 let ptr = realloc(ptr, layout, new_size);
456 if !ptr.is_null() {
457 return ptr;
458 }
459 }
460 malloc_failure();
461}
462
463#[cold]
464fn malloc_failure() -> ! {
465 cfg_if::cfg_if! {
466 if #[cfg(debug_assertions)] {
467 super::throw_str("invalid malloc request")
468 } else if #[cfg(feature = "std")] {
469 std::process::abort();
470 } else if #[cfg(all(
471 target_arch = "wasm32",
472 any(target_os = "unknown", target_os = "none")
473 ))] {
474 core::arch::wasm32::unreachable();
475 } else {
476 unreachable!()
477 }
478 }
479}
480
481#[no_mangle]
482pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
483 if size == 0 {
486 return;
487 }
488 let layout = Layout::from_size_align_unchecked(size, align);
489 dealloc(ptr, layout);
490}
491
492#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
526pub fn link_mem_intrinsics() {
527 crate::link::link_intrinsics();
528}
529
530#[cfg_attr(target_feature = "atomics", thread_local)]
531static GLOBAL_EXNDATA: Wrapper<Cell<[u32; 2]>> = Wrapper(Cell::new([0; 2]));
532
533#[no_mangle]
534pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
535 debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
536 GLOBAL_EXNDATA.0.set([1, idx]);
537}
538
539pub fn take_last_exception() -> Result<(), super::JsValue> {
540 let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
541 Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
542 } else {
543 Ok(())
544 };
545 GLOBAL_EXNDATA.0.set([0, 0]);
546 ret
547}
548
549pub trait IntoJsResult {
554 fn into_js_result(self) -> Result<JsValue, JsValue>;
555}
556
557impl IntoJsResult for () {
558 fn into_js_result(self) -> Result<JsValue, JsValue> {
559 Ok(JsValue::undefined())
560 }
561}
562
563impl<T: Into<JsValue>> IntoJsResult for T {
564 fn into_js_result(self) -> Result<JsValue, JsValue> {
565 Ok(self.into())
566 }
567}
568
569impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
570 fn into_js_result(self) -> Result<JsValue, JsValue> {
571 match self {
572 Ok(e) => Ok(e.into()),
573 Err(e) => Err(e.into()),
574 }
575 }
576}
577
578impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
579 fn into_js_result(self) -> Result<JsValue, JsValue> {
580 match self {
581 Ok(()) => Ok(JsValue::undefined()),
582 Err(e) => Err(e.into()),
583 }
584 }
585}
586
587pub trait Start {
590 fn start(self);
591}
592
593impl Start for () {
594 #[inline]
595 fn start(self) {}
596}
597
598impl<E: Into<JsValue>> Start for Result<(), E> {
599 #[inline]
600 fn start(self) {
601 if let Err(e) = self {
602 crate::throw_val(e.into());
603 }
604 }
605}
606
607pub struct MainWrapper<T>(pub Option<T>);
610
611pub trait Main {
612 fn __wasm_bindgen_main(&mut self);
613}
614
615impl Main for &mut &mut MainWrapper<()> {
616 #[inline]
617 fn __wasm_bindgen_main(&mut self) {}
618}
619
620impl Main for &mut &mut MainWrapper<Infallible> {
621 #[inline]
622 fn __wasm_bindgen_main(&mut self) {}
623}
624
625impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
626 #[inline]
627 fn __wasm_bindgen_main(&mut self) {
628 if let Err(e) = self.0.take().unwrap() {
629 crate::throw_val(e.into());
630 }
631 }
632}
633
634impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
635 #[inline]
636 fn __wasm_bindgen_main(&mut self) {
637 if let Err(e) = self.0.take().unwrap() {
638 crate::throw_str(&alloc::format!("{:?}", e));
639 }
640 }
641}
642
643pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
644 let mut len = 0;
645 let mut i = 0;
646 while i < slices.len() {
647 len += slices[i].len();
648 i += 1;
649 }
650 len
651}
652
653pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
654 slices: [&[u8]; SIZE],
655) -> [u8; RESULT_LEN] {
656 let mut result = [0; RESULT_LEN];
657
658 let mut slice_index = 0;
659 let mut result_offset = 0;
660
661 while slice_index < slices.len() {
662 let mut i = 0;
663 let slice = slices[slice_index];
664 while i < slice.len() {
665 result[result_offset] = slice[i];
666 i += 1;
667 result_offset += 1;
668 }
669 slice_index += 1;
670 }
671
672 result
673}
674
675pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
679 let mut result: [u8; 5] = [0; 5];
680 let mut i = 0;
681 while i < 4 {
682 result[i] = ((value >> (7 * i)) | 0x80) as u8;
683 i += 1;
684 }
685 result[4] = (value >> (7 * 4)) as u8;
686 result
687}
688
689pub trait VectorIntoJsValue: Sized {
692 fn vector_into_jsvalue(vector: Box<[Self]>) -> JsValue;
693}
694
695impl<T: VectorIntoJsValue> From<Box<[T]>> for JsValue {
696 fn from(vector: Box<[T]>) -> Self {
697 T::vector_into_jsvalue(vector)
698 }
699}
700
701pub fn js_value_vector_into_jsvalue<T: Into<JsValue>>(vector: Box<[T]>) -> JsValue {
702 let result = unsafe { JsValue::_new(super::__wbindgen_array_new()) };
703 for value in vector.into_vec() {
704 let js: JsValue = value.into();
705 unsafe { super::__wbindgen_array_push(result.idx, js.idx) }
706 mem::forget(js);
709 }
710 result
711}