1use super::{ProviderConstructionRequirements, ProviderConstructions};
2use crate::{
3 HostCall, HostCallError, HostCallable, HostProfile, HostProvider, HostType, HostTypeSequence,
4};
5use std::marker::PhantomData;
6
7type CallbackContextMarker<Profile, Provider, Return> =
8 PhantomData<fn() -> (Profile, Provider, Return)>;
9
10pub struct Callback<Signature, Context = MissingCallbackContext> {
16 context: Context,
17 signature: PhantomData<fn() -> Signature>,
18}
19
20#[doc(hidden)]
21pub struct MissingCallbackContext;
22
23#[doc(hidden)]
26pub trait ProviderCallbackCodec<'call, Profile, Provider, Return>
27where
28 Profile: HostProfile,
29 Provider: HostProvider<Profile>,
30 Return: HostType,
31{
32 type HostArguments: HostTypeSequence;
33 type HostReturn: HostType;
34 type Arguments;
35 type Returned;
36 type Requirements: ProviderConstructionRequirements;
37
38 fn into_host_arguments(
39 arguments: Self::Arguments,
40 call: &mut HostCall<'call, Profile, Provider, Return>,
41 constructions: &ProviderConstructions<'call, Self::Requirements>,
42 ) -> <Self::HostArguments as HostTypeSequence>::Values<'call>;
43
44 fn from_host_return(
45 value: <Self::HostReturn as HostType>::Value<'call>,
46 call: &mut HostCall<'call, Profile, Provider, Return>,
47 ) -> Self::Returned;
48}
49
50#[doc(hidden)]
52pub struct ProviderCallbackContext<'call, Profile, Provider, Return, Codec>
53where
54 Profile: HostProfile,
55 Provider: HostProvider<Profile>,
56 Return: HostType,
57 Codec: ProviderCallbackCodec<'call, Profile, Provider, Return>,
58{
59 callable: HostCallable<'call, Codec::HostArguments, Codec::HostReturn>,
60 constructions: ProviderConstructions<'call, Codec::Requirements>,
61 context: CallbackContextMarker<Profile, Provider, Return>,
62}
63
64impl<'call, Signature, Profile, Provider, Return, Codec>
65 Callback<Signature, ProviderCallbackContext<'call, Profile, Provider, Return, Codec>>
66where
67 Profile: HostProfile,
68 Provider: HostProvider<Profile>,
69 Return: HostType,
70 Codec: ProviderCallbackCodec<'call, Profile, Provider, Return>,
71{
72 #[doc(hidden)]
73 pub fn from_host(
74 callable: HostCallable<'call, Codec::HostArguments, Codec::HostReturn>,
75 constructions: ProviderConstructions<'call, Codec::Requirements>,
76 ) -> Self {
77 Self {
78 context: ProviderCallbackContext {
79 callable,
80 constructions,
81 context: PhantomData,
82 },
83 signature: PhantomData,
84 }
85 }
86
87 pub(crate) fn invoke(
88 self,
89 call: &mut HostCall<'call, Profile, Provider, Return>,
90 arguments: Codec::Arguments,
91 ) -> Result<Codec::Returned, HostCallError> {
92 let arguments = Codec::into_host_arguments(arguments, call, &self.context.constructions);
93 let returned = call.invoke(self.context.callable, arguments)?;
94 Ok(Codec::from_host_return(returned, call))
95 }
96}
97
98impl<'call, Profile, Provider, Return, Codec> Clone
99 for ProviderCallbackContext<'call, Profile, Provider, Return, Codec>
100where
101 Profile: HostProfile,
102 Provider: HostProvider<Profile>,
103 Return: HostType,
104 Codec: ProviderCallbackCodec<'call, Profile, Provider, Return>,
105{
106 fn clone(&self) -> Self {
107 *self
108 }
109}
110
111impl<'call, Profile, Provider, Return, Codec> Copy
112 for ProviderCallbackContext<'call, Profile, Provider, Return, Codec>
113where
114 Profile: HostProfile,
115 Provider: HostProvider<Profile>,
116 Return: HostType,
117 Codec: ProviderCallbackCodec<'call, Profile, Provider, Return>,
118{
119}
120
121impl<Signature, Context> Clone for Callback<Signature, Context>
122where
123 Context: Clone,
124{
125 fn clone(&self) -> Self {
126 Self {
127 context: self.context.clone(),
128 signature: PhantomData,
129 }
130 }
131}
132
133impl<Signature, Context> Copy for Callback<Signature, Context> where Context: Copy {}