linera_wasmer/
native_type.rs

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