wasm_bindgen/rt/
mod.rs

1use crate::convert::{FromWasmAbi, IntoWasmAbi, WasmAbi, WasmRet};
2use crate::describe::inform;
3use crate::JsValue;
4use core::borrow::{Borrow, BorrowMut};
5use core::cell::{Cell, UnsafeCell};
6use core::convert::Infallible;
7use core::ops::{Deref, DerefMut};
8#[cfg(target_feature = "atomics")]
9use core::sync::atomic::{AtomicU8, Ordering};
10use wasm_bindgen_shared::tys::FUNCTION;
11
12use alloc::alloc::{alloc, dealloc, realloc, Layout};
13use alloc::rc::Rc;
14use once_cell::unsync::Lazy;
15
16pub extern crate alloc;
17pub extern crate core;
18#[cfg(feature = "std")]
19pub extern crate std;
20
21pub mod marker;
22
23pub use wasm_bindgen_macro::BindgenedStruct;
24
25// Cast between arbitrary types supported by wasm-bindgen by going via JS.
26//
27// The implementation generates a no-op JS adapter that simply takes an argument
28// in one type, decodes it from the ABI, and then returns the same value back
29// encoded with a different type.
30pub fn wbg_cast<From: IntoWasmAbi, To: FromWasmAbi>(value: From) -> To {
31    // Here we need to create a conversion function between arbitrary types
32    // supported by the wasm-bindgen's ABI.
33    // To do that we... take a few unconventional turns.
34    // In essence what happens here is this:
35    //
36    // 1. First up, below we call a function, `breaks_if_inlined`. This
37    //    function, as the name implies, does not work if it's inlined.
38    //    More on that in a moment.
39    // 2. This is actually a descriptor function, similar to ones we
40    //    generate for imports and exports, except we can't name it here
41    //    because it's generated by monomorphisation for specific types.
42    // 2. Since we can't name it to associate with a specific import or
43    //    export, we use a different approach. After describing the input
44    //    type, this function internally calls a special import recognized
45    //    by the `wasm-bindgen` CLI tool, `__wbindgen_describe_cast`. This
46    //    imported symbol is similar to `__wbindgen_describe` in that it's
47    //    not intended to show up in the final binary but it's merely a
48    //    signal for `wasm-bindgen` that marks the parent function
49    //    (`breaks_if_inlined`) as a cast descriptor.
50    //
51    // Most of this doesn't actually make sense to happen at runtime! The
52    // real magic happens when `wasm-bindgen` comes along and updates our
53    // generated code. When `wasm-bindgen` runs it performs a few tasks:
54    //
55    // * First, it finds all functions that call
56    //   `__wbindgen_describe_cast`. These are all `breaks_if_inlined`
57    //   defined below as the symbol isn't called anywhere else.
58    // * Next, `wasm-bindgen` executes the `breaks_if_inlined`
59    //   monomorphized functions, passing it dummy arguments. This will
60    //   execute the function until it reaches the call to
61    //   `__wbindgen_describe_cast`, at which point the interpreter stops.
62    // * Finally, and probably most heinously, the call to
63    //   `breaks_if_inlined` is rewritten to call an otherwise globally
64    //   imported function. This globally imported function will simply
65    //   return the passed in argument, but because it's adapter for our
66    //   descriptors, what we get is actually a general JS cast going via
67    //   Rust input type -> ABI -> JS value -> Rust output type chain.
68
69    #[inline(never)]
70    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
71    unsafe extern "C" fn breaks_if_inlined<From: IntoWasmAbi, To: FromWasmAbi>(
72        prim1: <From::Abi as WasmAbi>::Prim1,
73        prim2: <From::Abi as WasmAbi>::Prim2,
74        prim3: <From::Abi as WasmAbi>::Prim3,
75        prim4: <From::Abi as WasmAbi>::Prim4,
76    ) -> WasmRet<To::Abi> {
77        inform(FUNCTION);
78        inform(0);
79        inform(1);
80        From::describe();
81        To::describe();
82        To::describe();
83        // Pass all inputs and outputs across the opaque FFI boundary to prevent
84        // compiler from removing them as dead code.
85        core::ptr::read(super::__wbindgen_describe_cast(
86            breaks_if_inlined::<From, To> as _,
87            &(prim1, prim2, prim3, prim4) as *const _ as _,
88        ) as _)
89    }
90
91    let (prim1, prim2, prim3, prim4) = value.into_abi().split();
92
93    unsafe { To::from_abi(breaks_if_inlined::<From, To>(prim1, prim2, prim3, prim4).join()) }
94}
95
96pub(crate) struct ThreadLocalWrapper<T>(pub(crate) T);
97
98#[cfg(not(target_feature = "atomics"))]
99unsafe impl<T> Sync for ThreadLocalWrapper<T> {}
100
101#[cfg(not(target_feature = "atomics"))]
102unsafe impl<T> Send for ThreadLocalWrapper<T> {}
103
104/// Wrapper around [`Lazy`] adding `Send + Sync` when `atomics` is not enabled.
105pub struct LazyCell<T, F = fn() -> T>(ThreadLocalWrapper<Lazy<T, F>>);
106
107impl<T, F> LazyCell<T, F> {
108    pub const fn new(init: F) -> LazyCell<T, F> {
109        Self(ThreadLocalWrapper(Lazy::new(init)))
110    }
111}
112
113impl<T, F: FnOnce() -> T> LazyCell<T, F> {
114    pub fn force(this: &Self) -> &T {
115        &this.0 .0
116    }
117}
118
119impl<T> Deref for LazyCell<T> {
120    type Target = T;
121
122    fn deref(&self) -> &T {
123        ::once_cell::unsync::Lazy::force(&self.0 .0)
124    }
125}
126
127#[cfg(not(target_feature = "atomics"))]
128pub use LazyCell as LazyLock;
129
130#[cfg(target_feature = "atomics")]
131pub struct LazyLock<T, F = fn() -> T> {
132    state: AtomicU8,
133    data: UnsafeCell<Data<T, F>>,
134}
135
136#[cfg(target_feature = "atomics")]
137enum Data<T, F> {
138    Value(T),
139    Init(F),
140}
141
142#[cfg(target_feature = "atomics")]
143impl<T, F> LazyLock<T, F> {
144    const STATE_UNINIT: u8 = 0;
145    const STATE_INITIALIZING: u8 = 1;
146    const STATE_INIT: u8 = 2;
147
148    pub const fn new(init: F) -> LazyLock<T, F> {
149        Self {
150            state: AtomicU8::new(Self::STATE_UNINIT),
151            data: UnsafeCell::new(Data::Init(init)),
152        }
153    }
154}
155
156#[cfg(target_feature = "atomics")]
157impl<T> Deref for LazyLock<T> {
158    type Target = T;
159
160    fn deref(&self) -> &T {
161        let mut state = self.state.load(Ordering::Acquire);
162
163        loop {
164            match state {
165                Self::STATE_INIT => {
166                    let Data::Value(value) = (unsafe { &*self.data.get() }) else {
167                        unreachable!()
168                    };
169                    return value;
170                }
171                Self::STATE_UNINIT => {
172                    if let Err(new_state) = self.state.compare_exchange_weak(
173                        Self::STATE_UNINIT,
174                        Self::STATE_INITIALIZING,
175                        Ordering::Acquire,
176                        Ordering::Relaxed,
177                    ) {
178                        state = new_state;
179                        continue;
180                    }
181
182                    let data = unsafe { &mut *self.data.get() };
183                    let Data::Init(init) = data else {
184                        unreachable!()
185                    };
186                    *data = Data::Value(init());
187                    self.state.store(Self::STATE_INIT, Ordering::Release);
188                    state = Self::STATE_INIT;
189                }
190                Self::STATE_INITIALIZING => {
191                    // TODO: Block here if possible. This would require
192                    // detecting if we can in the first place.
193                    state = self.state.load(Ordering::Acquire);
194                }
195                _ => unreachable!(),
196            }
197        }
198    }
199}
200
201#[cfg(target_feature = "atomics")]
202unsafe impl<T, F: Sync> Sync for LazyLock<T, F> {}
203
204#[cfg(target_feature = "atomics")]
205unsafe impl<T, F: Send> Send for LazyLock<T, F> {}
206
207#[macro_export]
208#[doc(hidden)]
209#[cfg(not(target_feature = "atomics"))]
210macro_rules! __wbindgen_thread_local {
211    ($wasm_bindgen:tt, $actual_ty:ty) => {{
212        static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
213            $wasm_bindgen::__rt::LazyCell::new(init);
214        $wasm_bindgen::JsThreadLocal { __inner: &_VAL }
215    }};
216}
217
218#[macro_export]
219#[doc(hidden)]
220#[cfg(target_feature = "atomics")]
221#[allow_internal_unstable(thread_local)]
222macro_rules! __wbindgen_thread_local {
223    ($wasm_bindgen:tt, $actual_ty:ty) => {{
224        #[thread_local]
225        static _VAL: $wasm_bindgen::__rt::LazyCell<$actual_ty> =
226            $wasm_bindgen::__rt::LazyCell::new(init);
227        $wasm_bindgen::JsThreadLocal {
228            __inner: || unsafe { $wasm_bindgen::__rt::LazyCell::force(&_VAL) as *const $actual_ty },
229        }
230    }};
231}
232
233#[macro_export]
234#[doc(hidden)]
235#[cfg(not(wasm_bindgen_unstable_test_coverage))]
236macro_rules! __wbindgen_coverage {
237    ($item:item) => {
238        $item
239    };
240}
241
242#[macro_export]
243#[doc(hidden)]
244#[cfg(wasm_bindgen_unstable_test_coverage)]
245#[allow_internal_unstable(coverage_attribute)]
246macro_rules! __wbindgen_coverage {
247    ($item:item) => {
248        #[coverage(off)]
249        $item
250    };
251}
252
253#[inline]
254pub fn assert_not_null<T>(s: *mut T) {
255    if s.is_null() {
256        throw_null();
257    }
258}
259
260#[cold]
261#[inline(never)]
262fn throw_null() -> ! {
263    super::throw_str("null pointer passed to rust");
264}
265
266/// A vendored version of `RefCell` from the standard library.
267///
268/// Now why, you may ask, would we do that? Surely `RefCell` in libstd is
269/// quite good. And you're right, it is indeed quite good! Functionally
270/// nothing more is needed from `RefCell` in the standard library but for
271/// now this crate is also sort of optimizing for compiled code size.
272///
273/// One major factor to larger binaries in Rust is when a panic happens.
274/// Panicking in the standard library involves a fair bit of machinery
275/// (formatting, panic hooks, synchronization, etc). It's all worthwhile if
276/// you need it but for something like `WasmRefCell` here we don't actually
277/// need all that!
278///
279/// This is just a wrapper around all Rust objects passed to JS intended to
280/// guard accidental reentrancy, so this vendored version is intended solely
281/// to not panic in libstd. Instead when it "panics" it calls our `throw`
282/// function in this crate which raises an error in JS.
283pub struct WasmRefCell<T: ?Sized> {
284    borrow: Cell<usize>,
285    value: UnsafeCell<T>,
286}
287
288impl<T: ?Sized> WasmRefCell<T> {
289    pub fn new(value: T) -> WasmRefCell<T>
290    where
291        T: Sized,
292    {
293        WasmRefCell {
294            value: UnsafeCell::new(value),
295            borrow: Cell::new(0),
296        }
297    }
298
299    pub fn get_mut(&mut self) -> &mut T {
300        unsafe { &mut *self.value.get() }
301    }
302
303    pub fn borrow(&self) -> Ref<'_, T> {
304        unsafe {
305            if self.borrow.get() == usize::MAX {
306                borrow_fail();
307            }
308            self.borrow.set(self.borrow.get() + 1);
309            Ref {
310                value: &*self.value.get(),
311                borrow: &self.borrow,
312            }
313        }
314    }
315
316    pub fn borrow_mut(&self) -> RefMut<'_, T> {
317        unsafe {
318            if self.borrow.get() != 0 {
319                borrow_fail();
320            }
321            self.borrow.set(usize::MAX);
322            RefMut {
323                value: &mut *self.value.get(),
324                borrow: &self.borrow,
325            }
326        }
327    }
328
329    pub fn into_inner(self) -> T
330    where
331        T: Sized,
332    {
333        self.value.into_inner()
334    }
335}
336
337pub struct Ref<'b, T: ?Sized + 'b> {
338    value: &'b T,
339    borrow: &'b Cell<usize>,
340}
341
342impl<T: ?Sized> Deref for Ref<'_, T> {
343    type Target = T;
344
345    #[inline]
346    fn deref(&self) -> &T {
347        self.value
348    }
349}
350
351impl<T: ?Sized> Borrow<T> for Ref<'_, T> {
352    #[inline]
353    fn borrow(&self) -> &T {
354        self.value
355    }
356}
357
358impl<T: ?Sized> Drop for Ref<'_, T> {
359    fn drop(&mut self) {
360        self.borrow.set(self.borrow.get() - 1);
361    }
362}
363
364pub struct RefMut<'b, T: ?Sized + 'b> {
365    value: &'b mut T,
366    borrow: &'b Cell<usize>,
367}
368
369impl<T: ?Sized> Deref for RefMut<'_, T> {
370    type Target = T;
371
372    #[inline]
373    fn deref(&self) -> &T {
374        self.value
375    }
376}
377
378impl<T: ?Sized> DerefMut for RefMut<'_, T> {
379    #[inline]
380    fn deref_mut(&mut self) -> &mut T {
381        self.value
382    }
383}
384
385impl<T: ?Sized> Borrow<T> for RefMut<'_, T> {
386    #[inline]
387    fn borrow(&self) -> &T {
388        self.value
389    }
390}
391
392impl<T: ?Sized> BorrowMut<T> for RefMut<'_, T> {
393    #[inline]
394    fn borrow_mut(&mut self) -> &mut T {
395        self.value
396    }
397}
398
399impl<T: ?Sized> Drop for RefMut<'_, T> {
400    fn drop(&mut self) {
401        self.borrow.set(0);
402    }
403}
404
405fn borrow_fail() -> ! {
406    super::throw_str(
407        "recursive use of an object detected which would lead to \
408		 unsafe aliasing in rust",
409    );
410}
411
412/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a `Ref`
413/// to the contents of that `WasmRefCell`.
414///
415/// The `'static` requirement is an unfortunate consequence of how this
416/// is implemented.
417pub struct RcRef<T: ?Sized + 'static> {
418    // The 'static is a lie.
419    //
420    // We could get away without storing this, since we're in the same module as
421    // `WasmRefCell` and can directly manipulate its `borrow`, but I'm considering
422    // turning it into a wrapper around `std`'s `RefCell` to reduce `unsafe` in
423    // which case that would stop working. This also requires less `unsafe` as is.
424    //
425    // It's important that this goes before `Rc` so that it gets dropped first.
426    ref_: Ref<'static, T>,
427    _rc: Rc<WasmRefCell<T>>,
428}
429
430impl<T: ?Sized> RcRef<T> {
431    pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
432        let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow() };
433        Self { _rc: rc, ref_ }
434    }
435}
436
437impl<T: ?Sized> Deref for RcRef<T> {
438    type Target = T;
439
440    #[inline]
441    fn deref(&self) -> &T {
442        &self.ref_
443    }
444}
445
446impl<T: ?Sized> Borrow<T> for RcRef<T> {
447    #[inline]
448    fn borrow(&self) -> &T {
449        &self.ref_
450    }
451}
452
453/// A type that encapsulates an `Rc<WasmRefCell<T>>` as well as a
454/// `RefMut` to the contents of that `WasmRefCell`.
455///
456/// The `'static` requirement is an unfortunate consequence of how this
457/// is implemented.
458pub struct RcRefMut<T: ?Sized + 'static> {
459    ref_: RefMut<'static, T>,
460    _rc: Rc<WasmRefCell<T>>,
461}
462
463impl<T: ?Sized> RcRefMut<T> {
464    pub fn new(rc: Rc<WasmRefCell<T>>) -> Self {
465        let ref_ = unsafe { (*Rc::as_ptr(&rc)).borrow_mut() };
466        Self { _rc: rc, ref_ }
467    }
468}
469
470impl<T: ?Sized> Deref for RcRefMut<T> {
471    type Target = T;
472
473    #[inline]
474    fn deref(&self) -> &T {
475        &self.ref_
476    }
477}
478
479impl<T: ?Sized> DerefMut for RcRefMut<T> {
480    #[inline]
481    fn deref_mut(&mut self) -> &mut T {
482        &mut self.ref_
483    }
484}
485
486impl<T: ?Sized> Borrow<T> for RcRefMut<T> {
487    #[inline]
488    fn borrow(&self) -> &T {
489        &self.ref_
490    }
491}
492
493impl<T: ?Sized> BorrowMut<T> for RcRefMut<T> {
494    #[inline]
495    fn borrow_mut(&mut self) -> &mut T {
496        &mut self.ref_
497    }
498}
499
500#[no_mangle]
501pub extern "C" fn __wbindgen_malloc(size: usize, align: usize) -> *mut u8 {
502    if let Ok(layout) = Layout::from_size_align(size, align) {
503        unsafe {
504            if layout.size() > 0 {
505                let ptr = alloc(layout);
506                if !ptr.is_null() {
507                    return ptr;
508                }
509            } else {
510                return align as *mut u8;
511            }
512        }
513    }
514
515    malloc_failure();
516}
517
518#[no_mangle]
519pub unsafe extern "C" fn __wbindgen_realloc(
520    ptr: *mut u8,
521    old_size: usize,
522    new_size: usize,
523    align: usize,
524) -> *mut u8 {
525    debug_assert!(old_size > 0);
526    debug_assert!(new_size > 0);
527    if let Ok(layout) = Layout::from_size_align(old_size, align) {
528        let ptr = realloc(ptr, layout, new_size);
529        if !ptr.is_null() {
530            return ptr;
531        }
532    }
533    malloc_failure();
534}
535
536#[cold]
537fn malloc_failure() -> ! {
538    cfg_if::cfg_if! {
539        if #[cfg(debug_assertions)] {
540            super::throw_str("invalid malloc request")
541        } else if #[cfg(feature = "std")] {
542            std::process::abort();
543        } else if #[cfg(all(
544            target_arch = "wasm32",
545            any(target_os = "unknown", target_os = "none")
546        ))] {
547            core::arch::wasm32::unreachable();
548        } else {
549            unreachable!()
550        }
551    }
552}
553
554#[no_mangle]
555pub unsafe extern "C" fn __wbindgen_free(ptr: *mut u8, size: usize, align: usize) {
556    // This happens for zero-length slices, and in that case `ptr` is
557    // likely bogus so don't actually send this to the system allocator
558    if size == 0 {
559        return;
560    }
561    let layout = Layout::from_size_align_unchecked(size, align);
562    dealloc(ptr, layout);
563}
564
565/// This is a curious function necessary to get wasm-bindgen working today,
566/// and it's a bit of an unfortunate hack.
567///
568/// The general problem is that somehow we need the above two symbols to
569/// exist in the final output binary (__wbindgen_malloc and
570/// __wbindgen_free). These symbols may be called by JS for various
571/// bindings, so we for sure need to make sure they're exported.
572///
573/// The problem arises, though, when what if no Rust code uses the symbols?
574/// For all intents and purposes it looks to LLVM and the linker like the
575/// above two symbols are dead code, so they're completely discarded!
576///
577/// Specifically what happens is this:
578///
579/// * The above two symbols are generated into some object file inside of
580///   libwasm_bindgen.rlib
581/// * The linker, LLD, will not load this object file unless *some* symbol
582///   is loaded from the object. In this case, if the Rust code never calls
583///   __wbindgen_malloc or __wbindgen_free then the symbols never get linked
584///   in.
585/// * Later when `wasm-bindgen` attempts to use the symbols they don't
586///   exist, causing an error.
587///
588/// This function is a weird hack for this problem. We inject a call to this
589/// function in all generated code. Usage of this function should then
590/// ensure that the above two intrinsics are translated.
591///
592/// Due to how rustc creates object files this function (and anything inside
593/// it) will be placed into the same object file as the two intrinsics
594/// above. That means if this function is called and referenced we'll pull
595/// in the object file and link the intrinsics.
596///
597/// Ideas for how to improve this are most welcome!
598#[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
599pub fn link_mem_intrinsics() {
600    crate::link::link_intrinsics();
601}
602
603#[cfg_attr(target_feature = "atomics", thread_local)]
604static GLOBAL_EXNDATA: ThreadLocalWrapper<Cell<[u32; 2]>> = ThreadLocalWrapper(Cell::new([0; 2]));
605
606#[no_mangle]
607pub unsafe extern "C" fn __wbindgen_exn_store(idx: u32) {
608    debug_assert_eq!(GLOBAL_EXNDATA.0.get()[0], 0);
609    GLOBAL_EXNDATA.0.set([1, idx]);
610}
611
612pub fn take_last_exception() -> Result<(), super::JsValue> {
613    let ret = if GLOBAL_EXNDATA.0.get()[0] == 1 {
614        Err(super::JsValue::_new(GLOBAL_EXNDATA.0.get()[1]))
615    } else {
616        Ok(())
617    };
618    GLOBAL_EXNDATA.0.set([0, 0]);
619    ret
620}
621
622/// An internal helper trait for usage in `#[wasm_bindgen]` on `async`
623/// functions to convert the return value of the function to
624/// `Result<JsValue, JsValue>` which is what we'll return to JS (where an
625/// error is a failed future).
626pub trait IntoJsResult {
627    fn into_js_result(self) -> Result<JsValue, JsValue>;
628}
629
630impl IntoJsResult for () {
631    fn into_js_result(self) -> Result<JsValue, JsValue> {
632        Ok(JsValue::undefined())
633    }
634}
635
636impl<T: Into<JsValue>> IntoJsResult for T {
637    fn into_js_result(self) -> Result<JsValue, JsValue> {
638        Ok(self.into())
639    }
640}
641
642impl<T: Into<JsValue>, E: Into<JsValue>> IntoJsResult for Result<T, E> {
643    fn into_js_result(self) -> Result<JsValue, JsValue> {
644        match self {
645            Ok(e) => Ok(e.into()),
646            Err(e) => Err(e.into()),
647        }
648    }
649}
650
651impl<E: Into<JsValue>> IntoJsResult for Result<(), E> {
652    fn into_js_result(self) -> Result<JsValue, JsValue> {
653        match self {
654            Ok(()) => Ok(JsValue::undefined()),
655            Err(e) => Err(e.into()),
656        }
657    }
658}
659
660/// An internal helper trait for usage in `#[wasm_bindgen(start)]`
661/// functions to throw the error (if it is `Err`).
662pub trait Start {
663    fn start(self);
664}
665
666impl Start for () {
667    #[inline]
668    fn start(self) {}
669}
670
671impl<E: Into<JsValue>> Start for Result<(), E> {
672    #[inline]
673    fn start(self) {
674        if let Err(e) = self {
675            crate::throw_val(e.into());
676        }
677    }
678}
679
680/// An internal helper struct for usage in `#[wasm_bindgen(main)]`
681/// functions to throw the error (if it is `Err`).
682pub struct MainWrapper<T>(pub Option<T>);
683
684pub trait Main {
685    fn __wasm_bindgen_main(&mut self);
686}
687
688impl Main for &mut &mut MainWrapper<()> {
689    #[inline]
690    fn __wasm_bindgen_main(&mut self) {}
691}
692
693impl Main for &mut &mut MainWrapper<Infallible> {
694    #[inline]
695    fn __wasm_bindgen_main(&mut self) {}
696}
697
698impl<E: Into<JsValue>> Main for &mut &mut MainWrapper<Result<(), E>> {
699    #[inline]
700    fn __wasm_bindgen_main(&mut self) {
701        if let Err(e) = self.0.take().unwrap() {
702            crate::throw_val(e.into());
703        }
704    }
705}
706
707impl<E: core::fmt::Debug> Main for &mut MainWrapper<Result<(), E>> {
708    #[inline]
709    fn __wasm_bindgen_main(&mut self) {
710        if let Err(e) = self.0.take().unwrap() {
711            crate::throw_str(&alloc::format!("{:?}", e));
712        }
713    }
714}
715
716pub const fn flat_len<T, const SIZE: usize>(slices: [&[T]; SIZE]) -> usize {
717    let mut len = 0;
718    let mut i = 0;
719    while i < slices.len() {
720        len += slices[i].len();
721        i += 1;
722    }
723    len
724}
725
726pub const fn flat_byte_slices<const RESULT_LEN: usize, const SIZE: usize>(
727    slices: [&[u8]; SIZE],
728) -> [u8; RESULT_LEN] {
729    let mut result = [0; RESULT_LEN];
730
731    let mut slice_index = 0;
732    let mut result_offset = 0;
733
734    while slice_index < slices.len() {
735        let mut i = 0;
736        let slice = slices[slice_index];
737        while i < slice.len() {
738            result[result_offset] = slice[i];
739            i += 1;
740            result_offset += 1;
741        }
742        slice_index += 1;
743    }
744
745    result
746}
747
748// NOTE: This method is used to encode u32 into a variable-length-integer during the compile-time .
749// Generally speaking, the length of the encoded variable-length-integer depends on the size of the integer
750// but the maximum capacity can be used here to simplify the amount of code during the compile-time .
751pub const fn encode_u32_to_fixed_len_bytes(value: u32) -> [u8; 5] {
752    let mut result: [u8; 5] = [0; 5];
753    let mut i = 0;
754    while i < 4 {
755        result[i] = ((value >> (7 * i)) | 0x80) as u8;
756        i += 1;
757    }
758    result[4] = (value >> (7 * 4)) as u8;
759    result
760}