use frunk::HList;
use crate::{
memory_layout::FlatLayout, primitive_types::FlatType, InstanceWithMemory, Layout, Memory,
Runtime, RuntimeError, RuntimeMemory, WitStore, WitType,
};
pub trait FlatHostParameters: FlatLayout {
type GuestParameters: FlatLayout;
fn lower_parameters<HostParameters, Instance>(
parameters: HostParameters,
memory: &mut Memory<'_, Instance>,
) -> Result<Self::GuestParameters, RuntimeError>
where
HostParameters: WitStore,
<HostParameters as WitType>::Layout: Layout<Flat = Self>,
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>;
}
macro_rules! direct_parameters {
($( $types:ident ),*) => {
impl<$( $types ),*> FlatHostParameters for HList![$( $types ),*]
where
$( $types: FlatType, )*
{
type GuestParameters = HList![$( $types ),*];
fn lower_parameters<Parameters, Instance>(
parameters: Parameters,
memory: &mut Memory<'_, Instance>,
) -> Result<Self::GuestParameters, RuntimeError>
where
Parameters: WitStore,
<Parameters as WitType>::Layout: Layout<Flat = Self>,
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
parameters.lower(memory)
}
}
};
}
repeat_macro!(direct_parameters => A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
impl<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, Tail> FlatHostParameters for HList![A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, ...Tail]
where
A: FlatType,
B: FlatType,
C: FlatType,
D: FlatType,
E: FlatType,
F: FlatType,
G: FlatType,
H: FlatType,
I: FlatType,
J: FlatType,
K: FlatType,
L: FlatType,
M: FlatType,
N: FlatType,
O: FlatType,
P: FlatType,
Q: FlatType,
Tail: FlatLayout,
{
type GuestParameters = HList![i32];
fn lower_parameters<Parameters, Instance>(
parameters: Parameters,
memory: &mut Memory<'_, Instance>,
) -> Result<Self::GuestParameters, RuntimeError>
where
Parameters: WitStore,
<Parameters as WitType>::Layout: Layout<Flat = Self>,
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
let location =
memory.allocate(Parameters::SIZE, <Parameters::Layout as Layout>::ALIGNMENT)?;
parameters.store(memory, location)?;
location.lower(memory)
}
}