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