use super::store::ExternalPayloadView;
use crate::host::type_::HostTypeAt;
use crate::host::{
HostCall, HostCallRuntime, HostProfile, HostProvider, HostType, HostTypeSequence,
};
use std::marker::PhantomData;
use std::ops::Deref;
pub struct HostStoredValue<Type> {
pub(crate) value: crate::runtime::StoredRuntimeValue,
marker: PhantomData<fn() -> Type>,
}
pub struct HostStoredType<Index>(PhantomData<Index>);
pub struct HostExternalPayloadBuilder<'runtime, Profile, Arguments>
where
Profile: HostProfile,
Arguments: HostTypeSequence,
{
pub(super) runtime: &'runtime mut dyn HostCallRuntime<Profile>,
arguments: PhantomData<Arguments>,
}
pub struct HostExternalPayloadView<'call, Payload, Arguments>
where
Arguments: HostTypeSequence,
{
pub(super) value: ExternalPayloadView<Payload>,
call: PhantomData<&'call Arguments>,
}
impl<Type> HostStoredValue<Type> {
pub(crate) fn new(value: crate::runtime::StoredRuntimeValue) -> Self {
Self {
value,
marker: PhantomData,
}
}
}
impl<'runtime, Profile, Arguments> HostExternalPayloadBuilder<'runtime, Profile, Arguments>
where
Profile: HostProfile,
Arguments: HostTypeSequence,
{
pub(crate) fn new(runtime: &'runtime mut dyn HostCallRuntime<Profile>) -> Self {
Self {
runtime,
arguments: PhantomData,
}
}
pub fn store<Type>(&mut self, value: Type::Value<'_>) -> HostStoredValue<Type>
where
Type: HostType,
{
HostStoredValue::new(
self.runtime
.retain_stored(crate::host::type_::into_scoped::<Type>(value)),
)
}
pub fn store_argument<Index>(
&mut self,
value: <<Arguments as HostTypeAt<Index>>::Type as HostType>::Value<'_>,
) -> HostStoredValue<HostStoredType<Index>>
where
Arguments: HostTypeAt<Index>,
{
HostStoredValue::new(
self.runtime
.retain_stored(crate::host::type_::into_scoped::<
<Arguments as HostTypeAt<Index>>::Type,
>(value)),
)
}
}
impl<'call, Payload, Arguments> HostExternalPayloadView<'call, Payload, Arguments>
where
Arguments: HostTypeSequence,
{
pub(crate) fn new(value: ExternalPayloadView<Payload>) -> Self {
Self {
value,
call: PhantomData,
}
}
pub fn restore<Profile, Provider, Return, Type>(
&self,
call: &mut HostCall<'call, Profile, Provider, Return>,
select: impl FnOnce(&Payload) -> &HostStoredValue<Type>,
) -> Type::Value<'call>
where
Profile: HostProfile,
Provider: HostProvider<Profile>,
Return: HostType,
Type: HostType,
{
call.restore_stored::<Type, Type>(select(&self.value))
}
pub fn restore_argument<Profile, Provider, Return, Index>(
&self,
call: &mut HostCall<'call, Profile, Provider, Return>,
select: impl FnOnce(&Payload) -> &HostStoredValue<HostStoredType<Index>>,
) -> <<Arguments as HostTypeAt<Index>>::Type as HostType>::Value<'call>
where
Profile: HostProfile,
Provider: HostProvider<Profile>,
Return: HostType,
Arguments: HostTypeAt<Index>,
{
call.restore_stored::<<Arguments as HostTypeAt<Index>>::Type, _>(select(&self.value))
}
}
impl<Payload, Arguments> Deref for HostExternalPayloadView<'_, Payload, Arguments>
where
Arguments: HostTypeSequence,
{
type Target = Payload;
fn deref(&self) -> &Self::Target {
&self.value
}
}