linera_witty/runtime/wasmer/
export_function.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Wasmer support for host functions exported to guests Wasm instances.
5
6#![allow(clippy::let_unit_value)]
7
8use std::error::Error;
9
10use wasmer::{FromToNativeWasmType, Function, FunctionEnvMut, WasmTypeList};
11
12use super::{Environment, InstanceBuilder};
13use crate::{primitive_types::MaybeFlatType, ExportFunction, RuntimeError};
14
15/// Implements [`ExportFunction`] for [`InstanceBuilder`] using the supported function signatures.
16macro_rules! export_function {
17    ($( $names:ident: $types:ident ),*) => {
18        impl<Handler, HandlerError, $( $types, )* FlatResult, UserData>
19            ExportFunction<Handler, ($( $types, )*), FlatResult> for InstanceBuilder<UserData>
20        where
21            $( $types: FromToNativeWasmType, )*
22            FlatResult: MaybeFlatType + WasmTypeList,
23            UserData: 'static,
24            HandlerError: Error + Send + Sync + 'static,
25            Handler:
26                Fn(
27                    FunctionEnvMut<'_, Environment<UserData>>,
28                    ($( $types, )*),
29                ) -> Result<FlatResult, HandlerError>
30                + Send
31                + Sync
32                + 'static,
33        {
34            fn export(
35                &mut self,
36                module_name: &str,
37                function_name: &str,
38                handler: Handler,
39            ) -> Result<(), RuntimeError> {
40                let environment = self.environment();
41
42                let function = Function::new_typed_with_env(
43                    self,
44                    &environment,
45                    move |
46                        environment: FunctionEnvMut<'_, Environment<UserData>>,
47                        $( $names: $types ),*
48                    | -> Result<FlatResult, wasmer::RuntimeError> {
49                        handler(environment, ($( $names, )*))
50                            .map_err(|error| -> Box<dyn std::error::Error + Send + Sync> {
51                                Box::new(error)
52                            })
53                            .map_err(wasmer::RuntimeError::user)
54                    },
55                );
56
57                self.define(
58                    module_name,
59                    function_name,
60                    function,
61                );
62
63                Ok(())
64            }
65        }
66    };
67}
68
69repeat_macro!(export_function =>
70    a: A,
71    b: B,
72    c: C,
73    d: D,
74    e: E,
75    f: F,
76    g: G,
77    h: H,
78    i: I,
79    j: J,
80    k: K,
81    l: L,
82    m: M,
83    n: N,
84    o: O,
85    p: P,
86    q: Q,
87);