wasmer/utils/native/
convert.rs

1pub use wasmer_types::NativeWasmType;
2use wasmer_types::{RawValue, Type};
3
4use crate::store::AsStoreRef;
5use crate::{
6    ExternRef, Function, TypedFunction,
7    vm::{VMExternRef, VMFuncRef},
8};
9
10use std::error::Error;
11use std::{
12    array::TryFromSliceError,
13    convert::{Infallible, TryInto},
14};
15
16use crate::store::AsStoreMut;
17
18/// `NativeWasmTypeInto` performs conversions from and into `NativeWasmType`
19/// types with a context.
20pub trait NativeWasmTypeInto: NativeWasmType + Sized {
21    #[doc(hidden)]
22    fn into_abi(self, store: &mut impl AsStoreMut) -> Self::Abi;
23
24    #[doc(hidden)]
25    unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self;
26
27    /// Convert self to raw value representation.
28    fn into_raw(self, store: &mut impl AsStoreMut) -> RawValue;
29
30    /// Convert to self from raw value representation.
31    ///
32    /// # Safety
33    ///
34    unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self;
35}
36
37impl NativeWasmTypeInto for i32 {
38    #[inline]
39    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
40        abi
41    }
42
43    #[inline]
44    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
45        self
46    }
47
48    #[inline]
49    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
50        RawValue { i32: self }
51    }
52
53    #[inline]
54    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
55        unsafe { raw.i32 }
56    }
57}
58
59impl NativeWasmTypeInto for u32 {
60    #[inline]
61    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
62        abi
63    }
64
65    #[inline]
66    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
67        self
68    }
69
70    #[inline]
71    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
72        RawValue { i32: self as _ }
73    }
74
75    #[inline]
76    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
77        unsafe { raw.i32 as _ }
78    }
79}
80
81impl NativeWasmTypeInto for i64 {
82    #[inline]
83    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
84        abi
85    }
86
87    #[inline]
88    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
89        self
90    }
91
92    #[inline]
93    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
94        RawValue { i64: self }
95    }
96
97    #[inline]
98    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
99        unsafe { raw.i64 }
100    }
101}
102
103impl NativeWasmTypeInto for u64 {
104    #[inline]
105    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
106        abi
107    }
108
109    #[inline]
110    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
111        self
112    }
113
114    #[inline]
115    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
116        RawValue { i64: self as _ }
117    }
118
119    #[inline]
120    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
121        unsafe { raw.i64 as _ }
122    }
123}
124
125impl NativeWasmTypeInto for f32 {
126    #[inline]
127    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
128        abi
129    }
130
131    #[inline]
132    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
133        self
134    }
135
136    #[inline]
137    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
138        RawValue { f32: self }
139    }
140
141    #[inline]
142    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
143        unsafe { raw.f32 }
144    }
145}
146
147impl NativeWasmTypeInto for f64 {
148    #[inline]
149    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
150        abi
151    }
152
153    #[inline]
154    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
155        self
156    }
157
158    #[inline]
159    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
160        RawValue { f64: self }
161    }
162
163    #[inline]
164    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
165        unsafe { raw.f64 }
166    }
167}
168
169impl NativeWasmTypeInto for u128 {
170    #[inline]
171    unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
172        abi
173    }
174
175    #[inline]
176    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
177        self
178    }
179
180    #[inline]
181    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
182        RawValue { u128: self }
183    }
184
185    #[inline]
186    unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: RawValue) -> Self {
187        unsafe { raw.u128 }
188    }
189}
190
191impl NativeWasmType for ExternRef {
192    const WASM_TYPE: Type = Type::ExternRef;
193    type Abi = usize;
194}
195
196impl NativeWasmTypeInto for Option<ExternRef> {
197    #[inline]
198    unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
199        match store.as_store_ref().inner.store {
200            #[cfg(feature = "sys")]
201            crate::BackendStore::Sys(_) => unsafe {
202                wasmer_vm::VMExternRef::from_raw(RawValue { externref: abi }).map(VMExternRef::Sys)
203            },
204            #[cfg(feature = "wamr")]
205            crate::BackendStore::Wamr(_) => unsafe {
206                crate::backend::wamr::vm::VMExternRef::from_raw(RawValue { externref: abi })
207                    .map(VMExternRef::Wamr)
208            },
209            #[cfg(feature = "wasmi")]
210            crate::BackendStore::Wasmi(_) => unsafe {
211                crate::backend::wasmi::vm::VMExternRef::from_raw(RawValue { externref: abi })
212                    .map(VMExternRef::Wasmi)
213            },
214            #[cfg(feature = "v8")]
215            crate::BackendStore::V8(_) => unsafe {
216                crate::backend::v8::vm::VMExternRef::from_raw(RawValue { externref: abi })
217                    .map(VMExternRef::V8)
218            },
219            #[cfg(feature = "js")]
220            crate::BackendStore::Js(_) => unsafe {
221                crate::backend::js::vm::VMExternRef::from_raw(RawValue { externref: abi })
222                    .map(VMExternRef::Js)
223            },
224            #[cfg(feature = "jsc")]
225            crate::BackendStore::Jsc(_) => unsafe {
226                crate::backend::jsc::vm::VMExternRef::from_raw(RawValue { externref: abi })
227                    .map(VMExternRef::Jsc)
228            },
229        }
230        .map(|e| unsafe { ExternRef::from_vm_externref(store, e) })
231    }
232
233    #[inline]
234    fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
235        self.map_or(0, |e| unsafe { e.vm_externref().into_raw().externref })
236    }
237
238    #[inline]
239    fn into_raw(self, _store: &mut impl AsStoreMut) -> RawValue {
240        self.map_or(RawValue { externref: 0 }, |e| e.vm_externref().into_raw())
241    }
242
243    #[inline]
244    unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self {
245        match store.as_store_ref().inner.store {
246            #[cfg(feature = "sys")]
247            crate::BackendStore::Sys(_) => unsafe {
248                wasmer_vm::VMExternRef::from_raw(raw).map(VMExternRef::Sys)
249            },
250            #[cfg(feature = "wamr")]
251            crate::BackendStore::Wamr(_) => unsafe {
252                crate::backend::wamr::vm::VMExternRef::from_raw(raw).map(VMExternRef::Wamr)
253            },
254            #[cfg(feature = "wasmi")]
255            crate::BackendStore::Wasmi(_) => unsafe {
256                crate::backend::wasmi::vm::VMExternRef::from_raw(raw).map(VMExternRef::Wasmi)
257            },
258            #[cfg(feature = "v8")]
259            crate::BackendStore::V8(_) => unsafe {
260                crate::backend::v8::vm::VMExternRef::from_raw(raw).map(VMExternRef::V8)
261            },
262            #[cfg(feature = "js")]
263            crate::BackendStore::Js(_) => unsafe {
264                crate::backend::js::vm::VMExternRef::from_raw(raw).map(VMExternRef::Js)
265            },
266            #[cfg(feature = "jsc")]
267            crate::BackendStore::Jsc(_) => unsafe {
268                crate::backend::jsc::vm::VMExternRef::from_raw(raw).map(VMExternRef::Jsc)
269            },
270        }
271        .map(|e| unsafe { ExternRef::from_vm_externref(store, e) })
272    }
273}
274
275impl<Args, Rets> From<TypedFunction<Args, Rets>> for Function
276where
277    Args: WasmTypeList,
278    Rets: WasmTypeList,
279{
280    fn from(other: TypedFunction<Args, Rets>) -> Self {
281        other.into_function()
282    }
283}
284
285impl NativeWasmType for Function {
286    const WASM_TYPE: Type = Type::FuncRef;
287    type Abi = usize;
288}
289
290impl NativeWasmTypeInto for Option<Function> {
291    #[inline]
292    unsafe fn from_abi(store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
293        match store.as_store_ref().inner.store {
294            #[cfg(feature = "sys")]
295            crate::BackendStore::Sys(_) => unsafe {
296                wasmer_vm::VMFuncRef::from_raw(RawValue { funcref: abi }).map(VMFuncRef::Sys)
297            },
298            #[cfg(feature = "wamr")]
299            crate::BackendStore::Wamr(_) => unsafe {
300                crate::backend::wamr::vm::VMFuncRef::from_raw(RawValue { funcref: abi })
301                    .map(VMFuncRef::Wamr)
302            },
303            #[cfg(feature = "wasmi")]
304            crate::BackendStore::Wasmi(_) => unsafe {
305                crate::backend::wasmi::vm::VMFuncRef::from_raw(RawValue { funcref: abi })
306                    .map(VMFuncRef::Wasmi)
307            },
308            #[cfg(feature = "v8")]
309            crate::BackendStore::V8(_) => unsafe {
310                crate::backend::v8::vm::VMFuncRef::from_raw(RawValue { funcref: abi })
311                    .map(VMFuncRef::V8)
312            },
313            #[cfg(feature = "js")]
314            crate::BackendStore::Js(_) => unsafe {
315                crate::backend::js::vm::VMFuncRef::from_raw(RawValue { funcref: abi })
316                    .map(VMFuncRef::Js)
317            },
318            #[cfg(feature = "jsc")]
319            crate::BackendStore::Jsc(_) => unsafe {
320                crate::backend::jsc::vm::VMFuncRef::from_raw(RawValue { funcref: abi })
321                    .map(VMFuncRef::Jsc)
322            },
323        }
324        .map(|f| unsafe { Function::from_vm_funcref(store, f) })
325    }
326
327    #[inline]
328    fn into_abi(self, store: &mut impl AsStoreMut) -> Self::Abi {
329        self.map_or(0, |f| unsafe { f.vm_funcref(store).into_raw().externref })
330    }
331
332    #[inline]
333    fn into_raw(self, store: &mut impl AsStoreMut) -> RawValue {
334        self.map_or(RawValue { externref: 0 }, |e| {
335            e.vm_funcref(store).into_raw()
336        })
337    }
338
339    #[inline]
340    unsafe fn from_raw(store: &mut impl AsStoreMut, raw: RawValue) -> Self {
341        match store.as_store_ref().inner.store {
342            #[cfg(feature = "sys")]
343            crate::BackendStore::Sys(_) => unsafe {
344                wasmer_vm::VMFuncRef::from_raw(raw).map(VMFuncRef::Sys)
345            },
346            #[cfg(feature = "wamr")]
347            crate::BackendStore::Wamr(_) => unsafe {
348                crate::backend::wamr::vm::VMFuncRef::from_raw(raw).map(VMFuncRef::Wamr)
349            },
350            #[cfg(feature = "wasmi")]
351            crate::BackendStore::Wasmi(_) => unsafe {
352                crate::backend::wasmi::vm::VMFuncRef::from_raw(raw).map(VMFuncRef::Wasmi)
353            },
354            #[cfg(feature = "v8")]
355            crate::BackendStore::V8(_) => unsafe {
356                crate::backend::v8::vm::VMFuncRef::from_raw(raw).map(VMFuncRef::V8)
357            },
358            #[cfg(feature = "js")]
359            crate::BackendStore::Js(_) => unsafe {
360                crate::backend::js::vm::VMFuncRef::from_raw(raw).map(VMFuncRef::Js)
361            },
362            #[cfg(feature = "jsc")]
363            crate::BackendStore::Jsc(_) => unsafe {
364                crate::backend::jsc::vm::VMFuncRef::from_raw(raw).map(VMFuncRef::Jsc)
365            },
366        }
367        .map(|f| unsafe { Function::from_vm_funcref(store, f) })
368    }
369}
370
371/// A trait to convert a Rust value to a `WasmNativeType` value,
372/// or to convert `WasmNativeType` value to a Rust value.
373///
374/// This trait should ideally be split into two traits:
375/// `FromNativeWasmType` and `ToNativeWasmType` but it creates a
376/// non-negligible complexity in the `WasmTypeList`
377/// implementation.
378///
379/// # Safety
380/// This trait is unsafe given the nature of how values are written and read from the native
381/// stack
382pub unsafe trait FromToNativeWasmType
383where
384    Self: Sized,
385{
386    /// Native Wasm type.
387    type Native: NativeWasmTypeInto;
388
389    /// Convert a value of kind `Self::Native` to `Self`.
390    ///
391    /// # Panics
392    ///
393    /// This method panics if `native` cannot fit in the `Self`
394    /// type`.
395    fn from_native(native: Self::Native) -> Self;
396
397    /// Convert self to `Self::Native`.
398    ///
399    /// # Panics
400    ///
401    /// This method panics if `self` cannot fit in the
402    /// `Self::Native` type.
403    fn to_native(self) -> Self::Native;
404
405    /// Returns whether the given value is from the given store.
406    ///
407    /// This always returns true for primitive types that can be used with
408    /// any context.
409    fn is_from_store(&self, _store: &impl AsStoreRef) -> bool {
410        true
411    }
412}
413
414macro_rules! from_to_native_wasm_type {
415    ( $( $type:ty => $native_type:ty ),* ) => {
416        $(
417            #[allow(clippy::use_self)]
418            unsafe impl FromToNativeWasmType for $type {
419                type Native = $native_type;
420
421                #[inline]
422                fn from_native(native: Self::Native) -> Self {
423                    native as Self
424                }
425
426                #[inline]
427                fn to_native(self) -> Self::Native {
428                    self as Self::Native
429                }
430            }
431        )*
432    };
433}
434
435macro_rules! from_to_native_wasm_type_same_size {
436    ( $( $type:ty => $native_type:ty ),* ) => {
437        $(
438            #[allow(clippy::use_self)]
439            unsafe impl FromToNativeWasmType for $type {
440                type Native = $native_type;
441
442                #[inline]
443                fn from_native(native: Self::Native) -> Self {
444                    Self::from_ne_bytes(Self::Native::to_ne_bytes(native))
445                }
446
447                #[inline]
448                fn to_native(self) -> Self::Native {
449                    Self::Native::from_ne_bytes(Self::to_ne_bytes(self))
450                }
451            }
452        )*
453    };
454}
455
456from_to_native_wasm_type!(
457    i8 => i32,
458    u8 => i32,
459    i16 => i32,
460    u16 => i32
461);
462
463from_to_native_wasm_type_same_size!(
464    i32 => i32,
465    u32 => i32,
466    i64 => i64,
467    u64 => i64,
468    f32 => f32,
469    f64 => f64
470);
471
472unsafe impl FromToNativeWasmType for Option<ExternRef> {
473    type Native = Self;
474
475    fn to_native(self) -> Self::Native {
476        self
477    }
478    fn from_native(n: Self::Native) -> Self {
479        n
480    }
481    fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
482        self.as_ref().is_none_or(|e| e.is_from_store(store))
483    }
484}
485
486unsafe impl FromToNativeWasmType for Option<Function> {
487    type Native = Self;
488
489    fn to_native(self) -> Self::Native {
490        self
491    }
492    fn from_native(n: Self::Native) -> Self {
493        n
494    }
495    fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
496        self.as_ref().is_none_or(|f| f.is_from_store(store))
497    }
498}
499
500#[cfg(test)]
501mod test_from_to_native_wasm_type {
502    use super::*;
503
504    #[test]
505    fn test_to_native() {
506        assert_eq!(7i8.to_native(), 7i32);
507        assert_eq!(7u8.to_native(), 7i32);
508        assert_eq!(7i16.to_native(), 7i32);
509        assert_eq!(7u16.to_native(), 7i32);
510        assert_eq!(u32::MAX.to_native(), -1);
511    }
512
513    #[test]
514    fn test_to_native_same_size() {
515        assert_eq!(7i32.to_native(), 7i32);
516        assert_eq!(7u32.to_native(), 7i32);
517        assert_eq!(7i64.to_native(), 7i64);
518        assert_eq!(7u64.to_native(), 7i64);
519        assert_eq!(7f32.to_native(), 7f32);
520        assert_eq!(7f64.to_native(), 7f64);
521    }
522}
523
524/// The `WasmTypeList` trait represents a tuple (list) of Wasm
525/// typed values. It is used to get low-level representation of
526/// such a tuple.
527pub trait WasmTypeList
528where
529    Self: Sized,
530{
531    /// The C type (a struct) that can hold/represent all the
532    /// represented values.
533    type CStruct;
534
535    /// The array type that can hold all the represented values.
536    ///
537    /// Note that all values are stored in their binary form.
538    type Array: AsMut<[RawValue]>;
539
540    /// The size of the array
541    fn size() -> u32;
542
543    /// Constructs `Self` based on an array of values.
544    ///
545    /// # Safety
546    unsafe fn from_array(store: &mut impl AsStoreMut, array: Self::Array) -> Self;
547
548    /// Constructs `Self` based on a slice of values.
549    ///
550    /// `from_slice` returns a `Result` because it is possible
551    /// that the slice doesn't have the same size than
552    /// `Self::Array`, in which circumstance an error of kind
553    /// `TryFromSliceError` will be returned.
554    ///
555    /// # Safety
556    unsafe fn from_slice(
557        store: &mut impl AsStoreMut,
558        slice: &[RawValue],
559    ) -> Result<Self, TryFromSliceError>;
560
561    /// Builds and returns an array of type `Array` from a tuple
562    /// (list) of values.
563    ///
564    /// # Safety
565    unsafe fn into_array(self, store: &mut impl AsStoreMut) -> Self::Array;
566
567    /// Allocates and return an empty array of type `Array` that
568    /// will hold a tuple (list) of values, usually to hold the
569    /// returned values of a WebAssembly function call.
570    fn empty_array() -> Self::Array;
571
572    /// Builds a tuple (list) of values from a C struct of type
573    /// `CStruct`.
574    ///
575    /// # Safety
576    unsafe fn from_c_struct(store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self;
577
578    /// Builds and returns a C struct of type `CStruct` from a
579    /// tuple (list) of values.
580    ///
581    /// # Safety
582    unsafe fn into_c_struct(self, store: &mut impl AsStoreMut) -> Self::CStruct;
583
584    /// Writes the contents of a C struct to an array of `RawValue`.
585    ///
586    /// # Safety
587    unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, ptr: *mut RawValue);
588
589    /// Get the Wasm types for the tuple (list) of currently
590    /// represented values.
591    fn wasm_types() -> &'static [Type];
592}
593
594/// The `IntoResult` trait turns a `WasmTypeList` into a
595/// `Result<WasmTypeList, Self::Error>`.
596///
597/// It is mostly used to turn result values of a Wasm function
598/// call into a `Result`.
599pub trait IntoResult<T>
600where
601    T: WasmTypeList,
602{
603    /// The error type for this trait.
604    type Error: Error + Sync + Send + 'static;
605
606    /// Transforms `Self` into a `Result`.
607    fn into_result(self) -> Result<T, Self::Error>;
608}
609
610impl<T> IntoResult<T> for T
611where
612    T: WasmTypeList,
613{
614    // `T` is not a `Result`, it's already a value, so no error
615    // can be built.
616    type Error = Infallible;
617
618    fn into_result(self) -> Result<Self, Infallible> {
619        Ok(self)
620    }
621}
622
623impl<T, E> IntoResult<T> for Result<T, E>
624where
625    T: WasmTypeList,
626    E: Error + Sync + Send + 'static,
627{
628    type Error = E;
629
630    fn into_result(self) -> Self {
631        self
632    }
633}
634
635#[cfg(test)]
636mod test_into_result {
637    use super::*;
638    use std::convert::Infallible;
639
640    #[test]
641    fn test_into_result_over_t() {
642        let x: i32 = 42;
643        let result_of_x: Result<i32, Infallible> = x.into_result();
644
645        assert_eq!(result_of_x.unwrap(), x);
646    }
647
648    #[test]
649    fn test_into_result_over_result() {
650        {
651            let x: Result<i32, Infallible> = Ok(42);
652            let result_of_x: Result<i32, Infallible> = x.into_result();
653
654            assert_eq!(result_of_x, x);
655        }
656
657        {
658            use std::{error, fmt};
659
660            #[derive(Debug, PartialEq)]
661            struct E;
662
663            impl fmt::Display for E {
664                fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
665                    write!(formatter, "E")
666                }
667            }
668
669            impl error::Error for E {}
670
671            let x: Result<Infallible, E> = Err(E);
672            let result_of_x: Result<Infallible, E> = x.into_result();
673
674            assert_eq!(result_of_x.unwrap_err(), E);
675        }
676    }
677}
678
679// Implement `WasmTypeList` on `Infallible`, which means that
680// `Infallible` can be used as a returned type of a host function
681// to express that it doesn't return, or to express that it cannot
682// fail (with `Result<_, Infallible>`).
683impl WasmTypeList for Infallible {
684    type CStruct = Self;
685    type Array = [RawValue; 0];
686
687    fn size() -> u32 {
688        0
689    }
690
691    unsafe fn from_array(_: &mut impl AsStoreMut, _: Self::Array) -> Self {
692        unreachable!()
693    }
694
695    unsafe fn from_slice(
696        _: &mut impl AsStoreMut,
697        _: &[RawValue],
698    ) -> Result<Self, TryFromSliceError> {
699        unreachable!()
700    }
701
702    unsafe fn into_array(self, _: &mut impl AsStoreMut) -> Self::Array {
703        []
704    }
705
706    fn empty_array() -> Self::Array {
707        []
708    }
709
710    unsafe fn from_c_struct(_: &mut impl AsStoreMut, self_: Self::CStruct) -> Self {
711        self_
712    }
713
714    unsafe fn into_c_struct(self, _: &mut impl AsStoreMut) -> Self::CStruct {
715        self
716    }
717
718    unsafe fn write_c_struct_to_ptr(_: Self::CStruct, _: *mut RawValue) {}
719
720    fn wasm_types() -> &'static [Type] {
721        &[]
722    }
723}
724
725macro_rules! impl_wasmtypelist {
726    ( [$c_struct_representation:ident]
727       $c_struct_name:ident,
728       $( $x:ident ),* ) => {
729
730        /// A structure with a C-compatible representation that can hold a set of Wasm values.
731        /// This type is used by `WasmTypeList::CStruct`.
732        #[repr($c_struct_representation)]
733        pub struct $c_struct_name< $( $x ),* > ( $( <<$x as FromToNativeWasmType>::Native as NativeWasmType>::Abi ),* )
734        where
735            $( $x: FromToNativeWasmType ),*;
736
737        // Implement `WasmTypeList` for a specific tuple.
738        #[allow(unused_parens, dead_code)]
739        impl< $( $x ),* >
740            WasmTypeList
741        for
742            ( $( $x ),* )
743        where
744            $( $x: FromToNativeWasmType ),*
745        {
746            type CStruct = $c_struct_name< $( $x ),* >;
747
748            type Array = [RawValue; count_idents!( $( $x ),* )];
749
750            fn size() -> u32 {
751                count_idents!( $( $x ),* ) as _
752            }
753
754            #[allow(unused_mut)]
755            #[allow(clippy::unused_unit)]
756            #[allow(clippy::missing_safety_doc)]
757            unsafe fn from_array(mut _store: &mut impl AsStoreMut, array: Self::Array) -> Self {
758                // Unpack items of the array.
759                #[allow(non_snake_case)]
760                let [ $( $x ),* ] = array;
761
762                // Build the tuple.
763                (
764                    $(
765                        {
766                            let native = unsafe { NativeWasmTypeInto::from_raw(_store, $x) };
767                            FromToNativeWasmType::from_native(native)
768                        }
769                    ),*
770                )
771            }
772
773            #[allow(clippy::missing_safety_doc)]
774            unsafe fn from_slice(store: &mut impl AsStoreMut, slice: &[RawValue]) -> Result<Self, TryFromSliceError> {
775                let array = slice.try_into()?;
776                Ok(unsafe { Self::from_array(store, array) })
777            }
778
779            #[allow(unused_mut)]
780            #[allow(clippy::missing_safety_doc)]
781            unsafe fn into_array(self, mut _store: &mut impl AsStoreMut) -> Self::Array {
782                // Unpack items of the tuple.
783                #[allow(non_snake_case)]
784                let ( $( $x ),* ) = self;
785
786                // Build the array.
787                [
788                    $(
789                        FromToNativeWasmType::to_native($x).into_raw(_store)
790                    ),*
791                ]
792            }
793
794            fn empty_array() -> Self::Array {
795                // Build an array initialized with `0`.
796                [RawValue { i32: 0 }; count_idents!( $( $x ),* )]
797            }
798
799            #[allow(unused_mut)]
800            #[allow(clippy::unused_unit)]
801            #[allow(clippy::missing_safety_doc)]
802            unsafe fn from_c_struct(mut _store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self {
803                // Unpack items of the C structure.
804                #[allow(non_snake_case)]
805                let $c_struct_name( $( $x ),* ) = c_struct;
806
807                (
808                    $(
809                        {
810                            let native = unsafe { NativeWasmTypeInto::from_abi(_store, $x) };
811                            FromToNativeWasmType::from_native(native)
812                        }
813                    ),*
814                )
815            }
816
817            #[allow(unused_parens, non_snake_case, unused_mut)]
818            #[allow(clippy::missing_safety_doc)]
819            unsafe fn into_c_struct(self, mut _store: &mut impl AsStoreMut) -> Self::CStruct {
820                // Unpack items of the tuple.
821                let ( $( $x ),* ) = self;
822
823                // Build the C structure.
824                $c_struct_name(
825                    $(
826                        FromToNativeWasmType::to_native($x).into_abi(_store)
827                    ),*
828                )
829            }
830
831            #[allow(non_snake_case)]
832            unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, _ptr: *mut RawValue) {
833                // Unpack items of the tuple.
834                let $c_struct_name( $( $x ),* ) = c_struct;
835
836                let mut _n = 0;
837                $(
838                    unsafe {
839                        *_ptr.add(_n).cast() = $x;
840                    }
841                    _n += 1;
842                )*
843            }
844
845            fn wasm_types() -> &'static [Type] {
846                &[
847                    $(
848                        $x::Native::WASM_TYPE
849                    ),*
850                ]
851            }
852        }
853
854    };
855}
856
857// Black-magic to count the number of identifiers at compile-time.
858macro_rules! count_idents {
859    ( $($idents:ident),* ) => {
860        {
861            #[allow(dead_code, non_camel_case_types)]
862            enum Idents { $( $idents, )* __CountIdentsLast }
863            const COUNT: usize = Idents::__CountIdentsLast as usize;
864            COUNT
865        }
866    };
867}
868
869// Here we go! Let's generate all the C struct and `WasmTypeList`
870// implementations.
871impl_wasmtypelist!([C] S0,);
872impl_wasmtypelist!([transparent] S1, A1);
873impl_wasmtypelist!([C] S2, A1, A2);
874impl_wasmtypelist!([C] S3, A1, A2, A3);
875impl_wasmtypelist!([C] S4, A1, A2, A3, A4);
876impl_wasmtypelist!([C] S5, A1, A2, A3, A4, A5);
877impl_wasmtypelist!([C] S6, A1, A2, A3, A4, A5, A6);
878impl_wasmtypelist!([C] S7, A1, A2, A3, A4, A5, A6, A7);
879impl_wasmtypelist!([C] S8, A1, A2, A3, A4, A5, A6, A7, A8);
880impl_wasmtypelist!([C] S9, A1, A2, A3, A4, A5, A6, A7, A8, A9);
881impl_wasmtypelist!([C] S10, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
882impl_wasmtypelist!([C] S11, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11);
883impl_wasmtypelist!([C] S12, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12);
884impl_wasmtypelist!([C] S13, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13);
885impl_wasmtypelist!([C] S14, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14);
886impl_wasmtypelist!([C] S15, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15);
887impl_wasmtypelist!([C] S16, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16);
888impl_wasmtypelist!([C] S17, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17);
889impl_wasmtypelist!([C] S18, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18);
890impl_wasmtypelist!([C] S19, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19);
891impl_wasmtypelist!([C] S20, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20);
892impl_wasmtypelist!([C] S21, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21);
893impl_wasmtypelist!([C] S22, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22);
894impl_wasmtypelist!([C] S23, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23);
895impl_wasmtypelist!([C] S24, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24);
896impl_wasmtypelist!([C] S25, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25);
897impl_wasmtypelist!([C] S26, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24, A25, A26);
898
899#[cfg(test)]
900mod test_wasm_type_list {
901    use super::*;
902    use wasmer_types::Type;
903    /*
904    #[test]
905    fn test_from_array() {
906        let mut store = Store::default();
907        let env = FunctionEnv::new(&mut store, ());
908        assert_eq!(<()>::from_array(&mut env, []), ());
909        assert_eq!(<i32>::from_array(&mut env, [RawValue{i32: 1}]), (1i32));
910        assert_eq!(<(i32, i64)>::from_array(&mut env, [RawValue{i32:1}, RawValue{i64:2}]), (1i32, 2i64));
911        assert_eq!(
912            <(i32, i64, f32, f64)>::from_array(&mut env, [
913                RawValue{i32:1},
914                RawValue{i64:2},
915                RawValue{f32: 3.1f32},
916                RawValue{f64: 4.2f64}
917            ]),
918            (1, 2, 3.1f32, 4.2f64)
919        );
920    }
921
922    #[test]
923    fn test_into_array() {
924        let mut store = Store::default();
925        let env = FunctionEnv::new(&mut store, ());
926        assert_eq!(().into_array(&mut store), [0i128; 0]);
927        assert_eq!((1i32).into_array(&mut store), [1i32]);
928        assert_eq!((1i32, 2i64).into_array(&mut store), [RawValue{i32: 1}, RawValue{i64: 2}]);
929        assert_eq!(
930            (1i32, 2i32, 3.1f32, 4.2f64).into_array(&mut store),
931            [RawValue{i32: 1}, RawValue{i32: 2}, RawValue{ f32: 3.1f32}, RawValue{f64: 4.2f64}]
932        );
933    }
934    */
935    #[test]
936    fn test_empty_array() {
937        assert_eq!(<()>::empty_array().len(), 0);
938        assert_eq!(<i32>::empty_array().len(), 1);
939        assert_eq!(<(i32, i64)>::empty_array().len(), 2);
940    }
941    /*
942    #[test]
943    fn test_from_c_struct() {
944        let mut store = Store::default();
945        let env = FunctionEnv::new(&mut store, ());
946        assert_eq!(<()>::from_c_struct(&mut store, S0()), ());
947        assert_eq!(<i32>::from_c_struct(&mut store, S1(1)), (1i32));
948        assert_eq!(<(i32, i64)>::from_c_struct(&mut store, S2(1, 2)), (1i32, 2i64));
949        assert_eq!(
950            <(i32, i64, f32, f64)>::from_c_struct(&mut store, S4(1, 2, 3.1, 4.2)),
951            (1i32, 2i64, 3.1f32, 4.2f64)
952        );
953    }
954    */
955    #[test]
956    fn test_wasm_types_for_uni_values() {
957        assert_eq!(<i32>::wasm_types(), [Type::I32]);
958        assert_eq!(<i64>::wasm_types(), [Type::I64]);
959        assert_eq!(<f32>::wasm_types(), [Type::F32]);
960        assert_eq!(<f64>::wasm_types(), [Type::F64]);
961    }
962
963    #[test]
964    fn test_wasm_types_for_multi_values() {
965        assert_eq!(<(i32, i32)>::wasm_types(), [Type::I32, Type::I32]);
966        assert_eq!(<(i64, i64)>::wasm_types(), [Type::I64, Type::I64]);
967        assert_eq!(<(f32, f32)>::wasm_types(), [Type::F32, Type::F32]);
968        assert_eq!(<(f64, f64)>::wasm_types(), [Type::F64, Type::F64]);
969
970        assert_eq!(
971            <(i32, i64, f32, f64)>::wasm_types(),
972            [Type::I32, Type::I64, Type::F32, Type::F64]
973        );
974    }
975}
976/*
977    #[allow(non_snake_case)]
978    #[cfg(test)]
979    mod test_function {
980        use super::*;
981        use crate::Store;
982        use crate::FunctionEnv;
983        use wasmer_types::Type;
984
985        fn func() {}
986        fn func__i32() -> i32 {
987            0
988        }
989        fn func_i32( _a: i32) {}
990        fn func_i32__i32( a: i32) -> i32 {
991            a * 2
992        }
993        fn func_i32_i32__i32( a: i32, b: i32) -> i32 {
994            a + b
995        }
996        fn func_i32_i32__i32_i32( a: i32, b: i32) -> (i32, i32) {
997            (a, b)
998        }
999        fn func_f32_i32__i32_f32( a: f32, b: i32) -> (i32, f32) {
1000            (b, a)
1001        }
1002
1003        #[test]
1004        fn test_function_types() {
1005            let mut store = Store::default();
1006            let env = FunctionEnv::new(&mut store, ());
1007            use wasmer_types::FunctionType;
1008            assert_eq!(
1009                StaticFunction::new(func).ty(&mut store),
1010                FunctionType::new(vec![], vec![])
1011            );
1012            assert_eq!(
1013                StaticFunction::new(func__i32).ty(&mut store),
1014                FunctionType::new(vec![], vec![Type::I32])
1015            );
1016            assert_eq!(
1017                StaticFunction::new(func_i32).ty(),
1018                FunctionType::new(vec![Type::I32], vec![])
1019            );
1020            assert_eq!(
1021                StaticFunction::new(func_i32__i32).ty(),
1022                FunctionType::new(vec![Type::I32], vec![Type::I32])
1023            );
1024            assert_eq!(
1025                StaticFunction::new(func_i32_i32__i32).ty(),
1026                FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32])
1027            );
1028            assert_eq!(
1029                StaticFunction::new(func_i32_i32__i32_i32).ty(),
1030                FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32])
1031            );
1032            assert_eq!(
1033                StaticFunction::new(func_f32_i32__i32_f32).ty(),
1034                FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32])
1035            );
1036        }
1037
1038        #[test]
1039        fn test_function_pointer() {
1040            let f = StaticFunction::new(func_i32__i32);
1041            let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) };
1042            assert_eq!(function(0, 3), 6);
1043        }
1044    }
1045*/
1046
1047#[cfg(test)]
1048mod test_native_type {
1049    use super::*;
1050    use wasmer_types::Type;
1051
1052    #[test]
1053    fn test_wasm_types() {
1054        assert_eq!(i32::WASM_TYPE, Type::I32);
1055        assert_eq!(i64::WASM_TYPE, Type::I64);
1056        assert_eq!(f32::WASM_TYPE, Type::F32);
1057        assert_eq!(f64::WASM_TYPE, Type::F64);
1058        assert_eq!(u128::WASM_TYPE, Type::V128);
1059    }
1060    /*
1061    #[test]
1062    fn test_roundtrip() {
1063        unsafe {
1064            assert_eq!(i32::from_raw(42i32.into_raw()), 42i32);
1065            assert_eq!(i64::from_raw(42i64.into_raw()), 42i64);
1066            assert_eq!(f32::from_raw(42f32.into_raw()), 42f32);
1067            assert_eq!(f64::from_raw(42f64.into_raw()), 42f64);
1068            assert_eq!(u128::from_raw(42u128.into_raw()), 42u128);
1069        }
1070    }
1071    */
1072}
1073
1074// pub trait IntegerAtomic
1075// where
1076//     Self: Sized
1077// {
1078//     type Primitive;
1079
1080//     fn add(&self, other: Self::Primitive) -> Self::Primitive;
1081//     fn sub(&self, other: Self::Primitive) -> Self::Primitive;
1082//     fn and(&self, other: Self::Primitive) -> Self::Primitive;
1083//     fn or(&self, other: Self::Primitive) -> Self::Primitive;
1084//     fn xor(&self, other: Self::Primitive) -> Self::Primitive;
1085//     fn load(&self) -> Self::Primitive;
1086//     fn store(&self, other: Self::Primitive) -> Self::Primitive;
1087//     fn compare_exchange(&self, expected: Self::Primitive, new: Self::Primitive) -> Self::Primitive;
1088//     fn swap(&self, other: Self::Primitive) -> Self::Primitive;
1089// }