1use super::{
16 utils::ReturnType,
17 Selector,
18};
19use crate::{
20 call::utils::DecodeMessageResult,
21 Environment,
22};
23use core::marker::PhantomData;
24use ink_prelude::vec::Vec;
25use ink_primitives::{
26 reflect::{
27 AbiDecodeWith,
28 AbiEncodeWith,
29 ScaleEncoding,
30 SolEncoding,
31 },
32 SolEncode,
33};
34
35pub struct Execution<Args, Output, Abi> {
37 pub input: ExecutionInput<Args, Abi>,
39 pub output: ReturnType<Output>,
41}
42
43impl<Args, Output, Abi> Execution<Args, Output, Abi>
44where
45 Args: AbiEncodeWith<Abi>,
46 Output: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
47{
48 pub fn new(input: ExecutionInput<Args, Abi>) -> Self {
50 Self {
51 input,
52 output: ReturnType::default(),
53 }
54 }
55
56 pub fn exec<I, E>(
58 self,
59 executor: &I,
60 ) -> Result<ink_primitives::MessageResult<Output>, I::Error>
61 where
62 E: Environment,
63 I: Executor<E>,
64 {
65 executor.exec(&self.input)
66 }
67}
68
69pub trait Executor<E: Environment> {
71 type Error;
73 fn exec<Args, Output, Abi>(
75 &self,
76 input: &ExecutionInput<Args, Abi>,
77 ) -> Result<ink_primitives::MessageResult<Output>, Self::Error>
78 where
79 Args: AbiEncodeWith<Abi>,
80 Output: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>;
81}
82
83#[derive(Clone, Default, Debug)]
85pub struct ExecutionInput<Args, Abi> {
86 selector: Selector,
88 args: Args,
90 _marker: PhantomData<Abi>,
91}
92
93impl<Abi> ExecutionInput<EmptyArgumentList<Abi>, Abi> {
94 #[inline]
96 pub fn new(selector: Selector) -> Self {
97 Self {
98 selector,
99 args: ArgumentList::empty(),
100 _marker: Default::default(),
101 }
102 }
103
104 #[inline]
106 pub fn push_arg<T>(
107 self,
108 arg: T,
109 ) -> ExecutionInput<ArgumentList<Argument<T>, EmptyArgumentList<Abi>, Abi>, Abi>
110 where
111 T: AbiEncodeWith<Abi>,
112 {
113 ExecutionInput {
114 selector: self.selector,
115 args: self.args.push_arg(arg),
116 _marker: Default::default(),
117 }
118 }
119}
120
121impl<Head, Rest, Abi> ExecutionInput<ArgumentList<Argument<Head>, Rest, Abi>, Abi> {
122 #[allow(clippy::type_complexity)]
124 #[inline]
125 pub fn push_arg<T>(
126 self,
127 arg: T,
128 ) -> ExecutionInput<ArgsList<T, ArgsList<Head, Rest, Abi>, Abi>, Abi>
129 where
130 T: AbiEncodeWith<Abi>,
131 {
132 ExecutionInput {
133 selector: self.selector,
134 args: self.args.push_arg(arg),
135 _marker: Default::default(),
136 }
137 }
138}
139
140impl<Args, Abi> ExecutionInput<Args, Abi> {
141 pub fn update_selector(&mut self, selector: Selector) {
146 self.selector = selector;
147 }
148}
149
150impl<Args, Abi> ExecutionInput<Args, Abi>
151where
152 Args: AbiEncodeWith<Abi>,
153{
154 pub fn encode(&self) -> Vec<u8> {
157 let mut encoded = Vec::new();
158 encoded.extend(self.selector.to_bytes());
159 self.args.encode_to_vec(&mut encoded);
160 encoded
161 }
162
163 pub fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
166 let selector_bytes = self.selector.to_bytes();
167 let selector_len = selector_bytes.len();
168
169 buffer[..selector_len].copy_from_slice(&selector_bytes);
170 let args_len = self.args.encode_to_slice(&mut buffer[selector_len..]);
171 selector_len + args_len
172 }
173}
174
175#[derive(Clone, Default, Debug)]
183pub struct ArgumentList<Head, Rest, Abi> {
184 head: Head,
186 rest: Rest,
188 _marker: PhantomData<Abi>,
189}
190
191pub type ArgsList<Head, Rest, Abi> = ArgumentList<Argument<Head>, Rest, Abi>;
193
194#[derive(Clone, Debug)]
196pub struct Argument<T> {
197 arg: T,
201}
202
203impl<T> Argument<T> {
204 #[inline]
206 fn new(arg: T) -> Self {
207 Self { arg }
208 }
209}
210
211#[derive(Clone, Default, Debug)]
213pub struct ArgumentListEnd;
214
215pub type EmptyArgumentList<Abi> = ArgumentList<ArgumentListEnd, ArgumentListEnd, Abi>;
217
218impl<Abi> EmptyArgumentList<Abi> {
219 #[inline]
221 pub fn empty() -> EmptyArgumentList<Abi> {
222 ArgumentList {
223 head: ArgumentListEnd,
224 rest: ArgumentListEnd,
225 _marker: Default::default(),
226 }
227 }
228
229 #[inline]
231 pub fn push_arg<T>(self, arg: T) -> ArgumentList<Argument<T>, Self, Abi>
232 where
233 T: AbiEncodeWith<Abi>,
234 {
235 ArgumentList {
236 head: Argument::new(arg),
237 rest: self,
238 _marker: Default::default(),
239 }
240 }
241}
242
243impl<Head, Rest, Abi> ArgumentList<Argument<Head>, Rest, Abi> {
244 #[inline]
246 pub fn push_arg<T>(self, arg: T) -> ArgumentList<Argument<T>, Self, Abi>
247 where
248 T: AbiEncodeWith<Abi>,
249 {
250 ArgumentList {
251 head: Argument::new(arg),
252 rest: self,
253 _marker: Default::default(),
254 }
255 }
256}
257
258impl<T> scale::Encode for Argument<T>
259where
260 T: scale::Encode,
261{
262 #[inline]
263 fn size_hint(&self) -> usize {
264 <T as scale::Encode>::size_hint(&self.arg)
265 }
266
267 #[inline]
268 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
269 <T as scale::Encode>::encode_to(&self.arg, output)
270 }
271}
272
273impl scale::Encode for EmptyArgumentList<ScaleEncoding> {
274 #[inline]
275 fn size_hint(&self) -> usize {
276 0
277 }
278
279 #[inline]
280 fn encode_to<O: scale::Output + ?Sized>(&self, _output: &mut O) {}
281}
282
283impl<Head, Rest> scale::Encode for ArgumentList<Argument<Head>, Rest, ScaleEncoding>
284where
285 Head: scale::Encode,
286 Rest: scale::Encode,
287{
288 #[inline]
289 fn size_hint(&self) -> usize {
290 scale::Encode::size_hint(&self.head)
291 .checked_add(scale::Encode::size_hint(&self.rest))
292 .expect("unable to checked_add")
293 }
294
295 #[inline]
296 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
297 scale::Encode::encode_to(&self.rest, output);
302 scale::Encode::encode_to(&self.head, output);
303 }
304}
305
306impl<Args> scale::Encode for ExecutionInput<Args, ScaleEncoding>
307where
308 Args: scale::Encode,
309{
310 #[inline]
311 fn size_hint(&self) -> usize {
312 scale::Encode::size_hint(&self.selector)
313 .checked_add(scale::Encode::size_hint(&self.args))
314 .expect("unable to checked_add")
315 }
316
317 #[inline]
318 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
319 scale::Encode::encode_to(&self.selector, output);
320 scale::Encode::encode_to(&self.args, output);
321 }
322}
323
324impl<'a, T> SolEncode<'a> for Argument<T>
325where
326 T: SolEncode<'a>,
327{
328 type SolType = <T as SolEncode<'a>>::SolType;
329
330 fn to_sol_type(&'a self) -> Self::SolType {
331 self.arg.to_sol_type()
332 }
333}
334
335impl SolEncode<'_> for EmptyArgumentList<SolEncoding> {
336 type SolType = ();
337
338 fn encode(&self) -> Vec<u8> {
339 Vec::new()
340 }
341
342 fn to_sol_type(&self) {}
344}
345
346impl<'a, Head, Rest> SolEncode<'a> for ArgumentList<Argument<Head>, Rest, SolEncoding>
347where
348 Head: SolEncode<'a>,
349 Rest: SolEncode<'a>,
350{
351 type SolType = (Rest::SolType, Head::SolType);
352
353 fn encode(&'a self) -> Vec<u8> {
354 let mut encoded = Vec::new();
355 encoded.extend(Rest::encode(&self.rest));
356 encoded.extend(Head::encode(&self.head.arg));
357 encoded
358 }
359
360 fn to_sol_type(&'a self) -> Self::SolType {
361 (self.rest.to_sol_type(), self.head.arg.to_sol_type())
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369
370 #[test]
371 fn empty_exec_input_works() {
372 let selector = Selector::new([0x01, 0x02, 0x03, 0x04]);
373 let exec_input = ExecutionInput::new(selector);
374 let encoded = scale::Encode::encode(&exec_input);
375 assert!(!encoded.is_empty());
376 let decoded = <Selector as scale::Decode>::decode(&mut &encoded[..]).unwrap();
377 assert_eq!(decoded, selector);
378 }
379
380 #[test]
381 fn empty_args_works() {
382 let empty_list = ArgumentList::empty();
383 let encoded = scale::Encode::encode(&empty_list);
384 assert_eq!(encoded, <Vec<u8>>::new());
385 }
386
387 #[test]
388 fn single_argument_works() {
389 let empty_list = ArgumentList::empty().push_arg(&1i32);
390 let encoded = scale::Encode::encode(&empty_list);
391 assert!(!encoded.is_empty());
392 let decoded = <i32 as scale::Decode>::decode(&mut &encoded[..]).unwrap();
393 assert_eq!(decoded, 1i32);
394 }
395
396 #[test]
397 fn multiple_arguments_works() {
398 let empty_list = ArgumentList::empty()
399 .push_arg(&42i32)
400 .push_arg(&true)
401 .push_arg(&[0x66u8; 4]);
402 let encoded = scale::Encode::encode(&empty_list);
403 assert!(!encoded.is_empty());
404 let decoded =
405 <(i32, bool, [u8; 4]) as scale::Decode>::decode(&mut &encoded[..]).unwrap();
406 assert_eq!(decoded, (42i32, true, [0x66; 4]));
407 }
408}