linera_witty/exported_function_interface/
mod.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Helper traits for exporting host functions to guest Wasm instances.
5//!
6//! These help determining the function signature the guest expects based on the host function
7//! signature.
8
9mod guest_interface;
10mod result_storage;
11
12use self::{guest_interface::GuestInterface, result_storage::ResultStorage};
13use crate::{
14    InstanceWithMemory, Layout, Memory, Runtime, RuntimeError, RuntimeMemory, WitLoad, WitStore,
15    WitType,
16};
17
18/// A type that can register some functions as exports for the target `Instance`.
19pub trait ExportTo<Instance> {
20    /// Registers some host functions as exports to the provided guest Wasm `instance`.
21    fn export_to(instance: &mut Instance) -> Result<(), RuntimeError>;
22}
23
24/// A type that accepts registering a host function as an export for a guest Wasm instance.
25///
26/// The `Handler` represents the closure type required for the host function, and `Parameters` and
27/// `Results` are the input and output types of the closure, respectively.
28pub trait ExportFunction<Handler, Parameters, Results> {
29    /// Registers a host function executed by the `handler` with the provided `module_name` and
30    /// `function_name` as an export for a guest Wasm instance.
31    fn export(
32        &mut self,
33        module_name: &str,
34        function_name: &str,
35        handler: Handler,
36    ) -> Result<(), RuntimeError>;
37}
38
39/// Representation of an exported host function's interface.
40///
41/// Implemented for a tuple pair of the host parameters type and the host results type, and allows
42/// converting to the signature the guest Wasm instance uses for that host function.
43pub trait ExportedFunctionInterface {
44    /// The type representing the host-side parameters.
45    type HostParameters: WitType;
46
47    /// The type representing the host-side results.
48    type HostResults: WitStore;
49
50    /// The representation of the guest-side function interface.
51    type GuestInterface: GuestInterface<
52        FlatHostParameters = <<Self::HostParameters as WitType>::Layout as Layout>::Flat,
53        ResultStorage = Self::ResultStorage,
54    >;
55
56    /// The type representing the guest-side parameters.
57    type GuestParameters;
58
59    /// The type representing the guest-side results.
60    type GuestResults;
61
62    /// How the results from the exported host function should be sent back to the guest.
63    type ResultStorage: ResultStorage<OutputFor<Self::HostResults> = Self::GuestResults>;
64
65    /// Converts the guest-side parameters into the host-side parameters.
66    fn lift_parameters<Instance>(
67        guest_parameters: Self::GuestParameters,
68        memory: &Memory<'_, Instance>,
69    ) -> Result<(Self::HostParameters, Self::ResultStorage), RuntimeError>
70    where
71        Instance: InstanceWithMemory,
72        <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>;
73
74    /// Converts the host-side results into the guest-side results.
75    fn lower_results<Instance>(
76        results: Self::HostResults,
77        result_storage: Self::ResultStorage,
78        memory: &mut Memory<'_, Instance>,
79    ) -> Result<Self::GuestResults, RuntimeError>
80    where
81        Instance: InstanceWithMemory,
82        <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>;
83}
84
85impl<Parameters, Results> ExportedFunctionInterface for (Parameters, Results)
86where
87    Parameters: WitLoad,
88    Results: WitStore,
89    (
90        <Parameters::Layout as Layout>::Flat,
91        <Results::Layout as Layout>::Flat,
92    ): GuestInterface<FlatHostParameters = <Parameters::Layout as Layout>::Flat>,
93    <() as WitType>::Layout: Layout<Flat = frunk::HNil>,
94{
95    type HostParameters = Parameters;
96    type HostResults = Results;
97    type GuestInterface = (
98        <Parameters::Layout as Layout>::Flat,
99        <Results::Layout as Layout>::Flat,
100    );
101    type GuestParameters = <Self::GuestInterface as GuestInterface>::FlatGuestParameters;
102    type GuestResults =
103        <<Self::GuestInterface as GuestInterface>::ResultStorage as ResultStorage>::OutputFor<
104            Self::HostResults,
105        >;
106    type ResultStorage = <Self::GuestInterface as GuestInterface>::ResultStorage;
107
108    fn lift_parameters<Instance>(
109        guest_parameters: Self::GuestParameters,
110        memory: &Memory<'_, Instance>,
111    ) -> Result<(Self::HostParameters, Self::ResultStorage), RuntimeError>
112    where
113        Instance: InstanceWithMemory,
114        <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
115    {
116        Self::GuestInterface::lift_parameters(guest_parameters, memory)
117    }
118
119    fn lower_results<Instance>(
120        results: Self::HostResults,
121        result_storage: Self::ResultStorage,
122        memory: &mut Memory<'_, Instance>,
123    ) -> Result<Self::GuestResults, RuntimeError>
124    where
125        Instance: InstanceWithMemory,
126        <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
127    {
128        result_storage.lower_result(results, memory)
129    }
130}