1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Implementations of [`InstanceWithFunction`] for Wasmer instances.

use frunk::{hlist_pat, HList};
use wasmer::{AsStoreRef, Extern, FromToNativeWasmType, NativeWasmTypeInto, TypedFunction};

use super::{
    parameters::WasmerParameters, results::WasmerResults, EntrypointInstance, ReentrantInstance,
};
use crate::{
    memory_layout::FlatLayout, primitive_types::FlatType, InstanceWithFunction, Runtime,
    RuntimeError,
};

/// Implements [`InstanceWithFunction`] for functions with the provided amount of parameters for
/// the [`EntrypointInstance`] and [`ReentrantInstance`] types.
macro_rules! impl_instance_with_function {
    ($( $names:ident : $types:ident ),*) => {
        impl_instance_with_function_for!(EntrypointInstance<UserData>, $( $names: $types ),*);
        impl_instance_with_function_for!(ReentrantInstance<'_, UserData>, $( $names: $types ),*);
    };
}

/// Implements [`InstanceWithFunction`] for functions with the provided amount of parameters for
/// the provided `instance` type.
macro_rules! impl_instance_with_function_for {
    ($instance:ty, $( $names:ident : $types:ident ),*) => {
        impl<$( $types, )* Results, UserData> InstanceWithFunction<HList![$( $types ),*], Results>
            for $instance
        where
            $( $types: FlatType + FromToNativeWasmType + NativeWasmTypeInto, )*
            Results: FlatLayout + WasmerResults,
            UserData: 'static,
        {
            type Function = TypedFunction<
                <HList![$( $types ),*] as WasmerParameters>::ImportParameters,
                <Results as WasmerResults>::Results,
            >;

            fn function_from_export(
                &mut self,
                export: <Self::Runtime as Runtime>::Export,
            ) -> Result<Option<Self::Function>, RuntimeError> {
                Ok(match export {
                    Extern::Function(function) => Some(function.typed(&self.as_store_ref())?),
                    _ => None,
                })
            }

            fn call(
                &mut self,
                function: &Self::Function,
                hlist_pat![$( $names ),*]: HList![$( $types ),*],
            ) -> Result<Results, RuntimeError> {
                let results = function.call(&mut *self, $( $names ),*)?;

                Ok(Results::from_wasmer(results))
            }
        }
    };
}

repeat_macro!(impl_instance_with_function =>
    a: A,
    b: B,
    c: C,
    d: D,
    e: E,
    f: F,
    g: G,
    h: H,
    i: I,
    j: J,
    k: K,
    l: L,
    m: M,
    n: N,
    o: O,
    p: P,
    q: Q
);