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
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

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

use wasmtime::{AsContext, AsContextMut, Extern, TypedFunc};

use super::{
    parameters::WasmtimeParameters, results::WasmtimeResults, EntrypointInstance, ReentrantInstance,
};
use crate::{memory_layout::FlatLayout, InstanceWithFunction, Runtime, RuntimeError};

/// Implements [`InstanceWithFunction`] for the Wasmtime [`Instance`] implementations.
macro_rules! impl_instance_with_function {
    ($instance:ty) => {
        impl<Parameters, Results, UserData> InstanceWithFunction<Parameters, Results> for $instance
        where
            Parameters: FlatLayout + WasmtimeParameters,
            Results: FlatLayout + WasmtimeResults,
        {
            type Function = TypedFunc<
                <Parameters as WasmtimeParameters>::Parameters,
                <Results as WasmtimeResults>::Results,
            >;

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

            fn call(
                &mut self,
                function: &Self::Function,
                parameters: Parameters,
            ) -> Result<Results, RuntimeError> {
                let results = function
                    .call(self.as_context_mut(), parameters.into_wasmtime())
                    .map_err(RuntimeError::Wasmtime)?;

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

impl_instance_with_function!(EntrypointInstance<UserData>);
impl_instance_with_function!(ReentrantInstance<'_, UserData>);