1#![no_std]
2
3extern crate alloc;
4
5use alloc::{boxed::Box, rc::Rc, vec::Vec};
6use core::{
7 cell::Cell,
8 future::Future,
9 marker::PhantomData,
10 pin::Pin,
11 task::{Context, Poll, Waker},
12};
13use evm::interpreter::{
14 error::{Capture, ExitError, ExitFatal, ExitResult},
15 FeedbackInterpreter, Interpreter,
16};
17
18pub trait FutureInterpreterAction<S, H> {
19 type Feedback;
20 type Trap;
21
22 fn run(
23 self,
24 state: &mut S,
25 retbuf: &mut Vec<u8>,
26 handle: &mut H,
27 ) -> Capture<Self::Feedback, Self::Trap>;
28}
29
30pub struct FutureInterpreterSubmit<A, F> {
31 action: Cell<Option<A>>,
32 action_feedback: Cell<Option<F>>,
33}
34
35impl<A, F> FutureInterpreterSubmit<A, F> {
36 fn new() -> Self {
37 Self {
38 action: Cell::new(None),
39 action_feedback: Cell::new(None),
40 }
41 }
42
43 pub fn submit(self: Rc<Self>, action: A) -> impl Future<Output = F> {
44 struct SubmitFuture<A, F>(Cell<Option<A>>, Rc<FutureInterpreterSubmit<A, F>>);
45
46 impl<A, F> Future for SubmitFuture<A, F> {
47 type Output = F;
48
49 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<F> {
50 let action_feedback = self.1.action_feedback.take();
51 if let Some(action_feedback) = action_feedback {
52 Poll::Ready(action_feedback)
53 } else {
54 let action = match self.0.replace(None) {
55 Some(action) => action,
56 None => panic!("future was already finished; should not be polled"),
57 };
58 self.1.action.set(Some(action));
59 Poll::Pending
60 }
61 }
62 }
63
64 SubmitFuture(Cell::new(Some(action)), self.clone())
65 }
66}
67
68pub struct FutureInterpreter<A, F, S, Tr> {
69 state: S,
70 retbuf: Vec<u8>,
71 inner: Pin<Box<dyn Future<Output = ExitResult>>>,
72 submit: Rc<FutureInterpreterSubmit<A, F>>,
73 _marker: PhantomData<Tr>,
74}
75
76impl<A, F, S, Tr> FutureInterpreter<A, F, S, Tr> {
77 pub fn new<Fn, Fu>(state: S, retbuf: Vec<u8>, f: Fn) -> Self
78 where
79 Fn: FnOnce(Rc<FutureInterpreterSubmit<A, F>>) -> Fu,
80 Fu: Future<Output = ExitResult> + 'static,
81 {
82 let submit = Rc::new(FutureInterpreterSubmit::new());
83 Self {
84 state,
85 retbuf,
86 inner: Box::pin(f(submit.clone())),
87 submit,
88 _marker: PhantomData,
89 }
90 }
91}
92
93impl<A, F, S, H, Tr> Interpreter<H> for FutureInterpreter<A, F, S, Tr>
94where
95 F: 'static,
96 A: FutureInterpreterAction<S, H, Feedback = F> + 'static,
97 Tr: From<A::Trap>,
98{
99 type State = S;
100 type Trap = Tr;
101
102 fn deconstruct(self) -> (S, Vec<u8>) {
103 (self.state, self.retbuf)
104 }
105
106 fn run(&mut self, handle: &mut H) -> Capture<ExitResult, Self::Trap> {
107 let waker = Waker::noop();
108 let mut ctx = Context::from_waker(waker);
109
110 loop {
111 match self.inner.as_mut().poll(&mut ctx) {
112 Poll::Ready(ret) => return Capture::Exit(ret),
113 Poll::Pending => {
114 let action = match self.submit.action.replace(None) {
115 Some(action) => action,
116 None => {
117 return Capture::Exit(
118 ExitFatal::Other("cannot advance future".into()).into(),
119 )
120 }
121 };
122
123 match action.run(&mut self.state, &mut self.retbuf, handle) {
124 Capture::Exit(feedback) => {
125 self.submit.action_feedback.set(Some(feedback));
126 }
127 Capture::Trap(trap) => return Capture::Trap(Box::new((*trap).into())),
128 }
129 }
130 }
131 }
132 }
133}
134
135impl<Feedback, A, F, S, H, Tr> FeedbackInterpreter<H, Feedback> for FutureInterpreter<A, F, S, Tr>
136where
137 F: 'static,
138 A: FutureInterpreterAction<S, H, Feedback = F> + 'static,
139 Tr: From<A::Trap>,
140 Feedback: Into<A::Feedback>,
141{
142 fn feedback(&mut self, feedback: Feedback, _handler: &mut H) -> Result<(), ExitError> {
143 let feedback: A::Feedback = feedback.into();
144 self.submit.action_feedback.set(Some(feedback));
145 Ok(())
146 }
147}