1use super::{
16 utils::ReturnType,
17 Selector,
18};
19use crate::{
20 call::utils::DecodeMessageResult,
21 Environment,
22};
23use alloy_sol_types::{
24 private::SolTypeValue,
25 SolType,
26 SolValue,
27 Word,
28};
29use core::marker::PhantomData;
30use ink_prelude::vec::Vec;
31use ink_primitives::reflect::{
32 AbiDecodeWith,
33 AbiEncodeWith,
34 ScaleEncoding,
35 SolEncoding,
36};
37
38pub struct Execution<Args, Output, Abi> {
40 pub input: ExecutionInput<Args, Abi>,
42 pub output: ReturnType<Output>,
44}
45
46impl<Args, Output, Abi> Execution<Args, Output, Abi>
47where
48 Args: AbiEncodeWith<Abi>,
49 Output: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>,
50{
51 pub fn new(input: ExecutionInput<Args, Abi>) -> Self {
53 Self {
54 input,
55 output: ReturnType::default(),
56 }
57 }
58
59 pub fn exec<I, E>(
61 self,
62 executor: &I,
63 ) -> Result<ink_primitives::MessageResult<Output>, I::Error>
64 where
65 E: Environment,
66 I: Executor<E>,
67 {
68 executor.exec(&self.input)
69 }
70}
71
72pub trait Executor<E: Environment> {
74 type Error;
76 fn exec<Args, Output, Abi>(
78 &self,
79 input: &ExecutionInput<Args, Abi>,
80 ) -> Result<ink_primitives::MessageResult<Output>, Self::Error>
81 where
82 Args: AbiEncodeWith<Abi>,
83 Output: AbiDecodeWith<Abi> + DecodeMessageResult<Abi>;
84}
85
86#[derive(Clone, Default, Debug)]
88pub struct ExecutionInput<Args, Abi> {
89 selector: Selector,
91 args: Args,
93 _marker: PhantomData<Abi>,
94}
95
96impl<Abi> ExecutionInput<EmptyArgumentList<Abi>, Abi> {
97 #[inline]
99 pub fn new(selector: Selector) -> Self {
100 Self {
101 selector,
102 args: ArgumentList::empty(),
103 _marker: Default::default(),
104 }
105 }
106
107 #[inline]
109 pub fn push_arg<T>(
110 self,
111 arg: T,
112 ) -> ExecutionInput<ArgumentList<Argument<T>, EmptyArgumentList<Abi>, Abi>, Abi>
113 where
114 T: AbiEncodeWith<Abi>,
115 {
116 ExecutionInput {
117 selector: self.selector,
118 args: self.args.push_arg(arg),
119 _marker: Default::default(),
120 }
121 }
122}
123
124impl<Head, Rest, Abi> ExecutionInput<ArgumentList<Argument<Head>, Rest, Abi>, Abi> {
125 #[allow(clippy::type_complexity)]
127 #[inline]
128 pub fn push_arg<T>(
129 self,
130 arg: T,
131 ) -> ExecutionInput<ArgsList<T, ArgsList<Head, Rest, Abi>, Abi>, Abi>
132 where
133 T: AbiEncodeWith<Abi>,
134 {
135 ExecutionInput {
136 selector: self.selector,
137 args: self.args.push_arg(arg),
138 _marker: Default::default(),
139 }
140 }
141}
142
143impl<Args, Abi> ExecutionInput<Args, Abi> {
144 pub fn update_selector(&mut self, selector: Selector) {
149 self.selector = selector;
150 }
151}
152
153impl<Args, Abi> ExecutionInput<Args, Abi>
154where
155 Args: AbiEncodeWith<Abi>,
156{
157 pub fn encode(&self) -> Vec<u8> {
160 let mut encoded = Vec::new();
161 encoded.extend(self.selector.to_bytes());
162 self.args.encode_to_vec(&mut encoded);
163 encoded
164 }
165
166 pub fn encode_to_slice(&self, buffer: &mut [u8]) -> usize {
169 let selector_bytes = self.selector.to_bytes();
170 let selector_len = selector_bytes.len();
171
172 buffer[..selector_len].copy_from_slice(&selector_bytes);
173 let args_len = self.args.encode_to_slice(&mut buffer[selector_len..]);
174 selector_len + args_len
175 }
176}
177
178#[derive(Clone, Default, Debug)]
186pub struct ArgumentList<Head, Rest, Abi> {
187 head: Head,
189 rest: Rest,
191 _marker: PhantomData<Abi>,
192}
193
194pub type ArgsList<Head, Rest, Abi> = ArgumentList<Argument<Head>, Rest, Abi>;
196
197#[derive(Clone, Debug)]
199pub struct Argument<T> {
200 arg: T,
204}
205
206impl<T> Argument<T> {
207 #[inline]
209 fn new(arg: T) -> Self {
210 Self { arg }
211 }
212}
213
214#[derive(Clone, Default, Debug)]
216pub struct ArgumentListEnd;
217
218pub type EmptyArgumentList<Abi> = ArgumentList<ArgumentListEnd, ArgumentListEnd, Abi>;
220
221impl<Abi> EmptyArgumentList<Abi> {
222 #[inline]
224 pub fn empty() -> EmptyArgumentList<Abi> {
225 ArgumentList {
226 head: ArgumentListEnd,
227 rest: ArgumentListEnd,
228 _marker: Default::default(),
229 }
230 }
231
232 #[inline]
234 pub fn push_arg<T>(self, arg: T) -> ArgumentList<Argument<T>, Self, Abi>
235 where
236 T: AbiEncodeWith<Abi>,
237 {
238 ArgumentList {
239 head: Argument::new(arg),
240 rest: self,
241 _marker: Default::default(),
242 }
243 }
244}
245
246impl<Head, Rest, Abi> ArgumentList<Argument<Head>, Rest, Abi> {
247 #[inline]
249 pub fn push_arg<T>(self, arg: T) -> ArgumentList<Argument<T>, Self, Abi>
250 where
251 T: AbiEncodeWith<Abi>,
252 {
253 ArgumentList {
254 head: Argument::new(arg),
255 rest: self,
256 _marker: Default::default(),
257 }
258 }
259}
260
261impl<T> scale::Encode for Argument<T>
262where
263 T: scale::Encode,
264{
265 #[inline]
266 fn size_hint(&self) -> usize {
267 <T as scale::Encode>::size_hint(&self.arg)
268 }
269
270 #[inline]
271 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
272 <T as scale::Encode>::encode_to(&self.arg, output)
273 }
274}
275
276impl scale::Encode for EmptyArgumentList<ScaleEncoding> {
277 #[inline]
278 fn size_hint(&self) -> usize {
279 0
280 }
281
282 #[inline]
283 fn encode_to<O: scale::Output + ?Sized>(&self, _output: &mut O) {}
284}
285
286impl<Head, Rest> scale::Encode for ArgumentList<Argument<Head>, Rest, ScaleEncoding>
287where
288 Head: scale::Encode,
289 Rest: scale::Encode,
290{
291 #[inline]
292 fn size_hint(&self) -> usize {
293 scale::Encode::size_hint(&self.head)
294 .checked_add(scale::Encode::size_hint(&self.rest))
295 .expect("unable to checked_add")
296 }
297
298 #[inline]
299 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
300 scale::Encode::encode_to(&self.rest, output);
305 scale::Encode::encode_to(&self.head, output);
306 }
307}
308
309impl<Args> scale::Encode for ExecutionInput<Args, ScaleEncoding>
310where
311 Args: scale::Encode,
312{
313 #[inline]
314 fn size_hint(&self) -> usize {
315 scale::Encode::size_hint(&self.selector)
316 .checked_add(scale::Encode::size_hint(&self.args))
317 .expect("unable to checked_add")
318 }
319
320 #[inline]
321 fn encode_to<O: scale::Output + ?Sized>(&self, output: &mut O) {
322 scale::Encode::encode_to(&self.selector, output);
323 scale::Encode::encode_to(&self.args, output);
324 }
325}
326
327impl<T> SolValue for Argument<T>
328where
329 T: SolValue,
330 Argument<T>: SolTypeValue<<T as SolValue>::SolType>,
331{
332 type SolType = <T as SolValue>::SolType;
333
334 fn abi_encode(&self) -> Vec<u8> {
335 <T as SolValue>::abi_encode(&self.arg)
336 }
337}
338
339impl SolTypeValue<()> for EmptyArgumentList<SolEncoding> {
340 fn stv_to_tokens(&self) -> <() as SolType>::Token<'_> {}
341
342 fn stv_abi_encode_packed_to(&self, _out: &mut Vec<u8>) {}
343
344 fn stv_eip712_data_word(&self) -> Word {
345 Word::from_slice(&[])
346 }
347}
348
349impl SolValue for EmptyArgumentList<SolEncoding> {
350 type SolType = ();
351
352 fn abi_encode(&self) -> Vec<u8> {
353 Vec::new()
354 }
355}
356
357impl<Head, Rest> SolTypeValue<(Rest::SolType, Head::SolType)>
358 for ArgumentList<Argument<Head>, Rest, SolEncoding>
359where
360 Head: SolValue,
361 Rest: SolValue,
362{
363 fn stv_to_tokens(
364 &self,
365 ) -> (
366 <Rest::SolType as SolType>::Token<'_>,
367 <Head::SolType as SolType>::Token<'_>,
368 ) {
369 (self.rest.stv_to_tokens(), self.head.arg.stv_to_tokens())
370 }
371
372 fn stv_abi_encode_packed_to(&self, out: &mut Vec<u8>) {
373 self.rest.stv_abi_encode_packed_to(out);
374 self.head.arg.stv_abi_encode_packed_to(out);
375 }
376
377 fn stv_eip712_data_word(&self) -> Word {
378 todo!("Implement EIP-712 encoding for ArgumentList")
379 }
380}
381
382impl<Head, Rest> SolValue for ArgumentList<Argument<Head>, Rest, SolEncoding>
383where
384 Head: SolValue,
385 Rest: SolValue,
386{
387 type SolType = (Rest::SolType, Head::SolType);
388
389 fn abi_encode(&self) -> Vec<u8> {
390 let mut encoded = Vec::new();
391 encoded.extend(Rest::abi_encode(&self.rest));
392 encoded.extend(Head::abi_encode(&self.head.arg));
393 encoded
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn empty_exec_input_works() {
403 let selector = Selector::new([0x01, 0x02, 0x03, 0x04]);
404 let exec_input = ExecutionInput::new(selector);
405 let encoded = scale::Encode::encode(&exec_input);
406 assert!(!encoded.is_empty());
407 let decoded = <Selector as scale::Decode>::decode(&mut &encoded[..]).unwrap();
408 assert_eq!(decoded, selector);
409 }
410
411 #[test]
412 fn empty_args_works() {
413 let empty_list = ArgumentList::empty();
414 let encoded = scale::Encode::encode(&empty_list);
415 assert_eq!(encoded, <Vec<u8>>::new());
416 }
417
418 #[test]
419 fn single_argument_works() {
420 let empty_list = ArgumentList::empty().push_arg(&1i32);
421 let encoded = scale::Encode::encode(&empty_list);
422 assert!(!encoded.is_empty());
423 let decoded = <i32 as scale::Decode>::decode(&mut &encoded[..]).unwrap();
424 assert_eq!(decoded, 1i32);
425 }
426
427 #[test]
428 fn multiple_arguments_works() {
429 let empty_list = ArgumentList::empty()
430 .push_arg(&42i32)
431 .push_arg(&true)
432 .push_arg(&[0x66u8; 4]);
433 let encoded = scale::Encode::encode(&empty_list);
434 assert!(!encoded.is_empty());
435 let decoded =
436 <(i32, bool, [u8; 4]) as scale::Decode>::decode(&mut &encoded[..]).unwrap();
437 assert_eq!(decoded, (42i32, true, [0x66; 4]));
438 }
439}