1use alloc::vec::Vec;
2
3use primitive_types::U256;
4
5use crate::error::{ExitError, ExitException};
6
7#[derive(Clone, Debug)]
9pub struct Stack {
10 data: Vec<U256>,
11 limit: usize,
12}
13
14macro_rules! impl_perform_popn_pushn {
15 (
16 $name:ident,
17 $pop_len:expr,
18 $push_len:expr,
19 ($($peek_pop:expr),*),
20 ($($peek_push:expr),*),
21 $pop_pushn_f:ident
22 ) => {
23 #[allow(unused_parens)]
28 pub fn $name<R, F>(&mut self, f: F) -> Result<R, ExitError> where
29 F: FnOnce(
30 $(impl_perform_popn_pushn!(INTERNAL_TYPE_RU256, $peek_pop)),*
31 ) -> Result<(($(impl_perform_popn_pushn!(INTERNAL_TYPE_U256, $peek_push)),*), R), ExitError>
32 {
33 match self.check_pop_push($pop_len, $push_len) {
34 Ok(()) => (),
35 Err(e) => return Err(e.into()),
36 }
37
38 let (p, ret) = match f($(self.unchecked_peek($peek_pop)),*) {
39 Ok(p1) => p1,
40 Err(e) => return Err(e.into()),
41 };
42 self.$pop_pushn_f($pop_len, p);
43
44 Ok(ret)
45 }
46 };
47 (INTERNAL_TYPE_RU256, $e:expr) => { &U256 };
48 (INTERNAL_TYPE_U256, $e:expr) => { U256 };
49}
50
51impl Stack {
52 #[must_use]
54 pub const fn new(limit: usize) -> Self {
55 Self {
56 data: Vec::new(),
57 limit,
58 }
59 }
60
61 #[inline]
63 #[must_use]
64 pub const fn limit(&self) -> usize {
65 self.limit
66 }
67
68 #[inline]
70 #[must_use]
71 pub fn len(&self) -> usize {
72 self.data.len()
73 }
74
75 #[inline]
77 #[must_use]
78 pub fn is_empty(&self) -> bool {
79 self.data.is_empty()
80 }
81
82 #[inline]
84 #[must_use]
85 pub const fn data(&self) -> &Vec<U256> {
86 &self.data
87 }
88
89 pub fn clear(&mut self) {
91 self.data.clear();
92 }
93
94 #[inline]
97 pub fn pop(&mut self) -> Result<U256, ExitException> {
98 self.data.pop().ok_or(ExitException::StackUnderflow)
99 }
100
101 #[inline]
105 pub fn push(&mut self, value: U256) -> Result<(), ExitException> {
106 if self.data.len() + 1 > self.limit {
107 return Err(ExitException::StackOverflow);
108 }
109 self.data.push(value);
110 Ok(())
111 }
112
113 pub fn check_pop_push(&self, pop: usize, push: usize) -> Result<(), ExitException> {
115 if self.data.len() < pop {
116 return Err(ExitException::StackUnderflow);
117 }
118 if self.data.len() - pop + push > self.limit {
119 return Err(ExitException::StackOverflow);
120 }
121 Ok(())
122 }
123
124 fn unchecked_peek(&self, no_from_top: usize) -> &U256 {
125 &self.data[self.data.len() - no_from_top - 1]
126 }
127
128 fn unchecked_pop_push1(&mut self, pop: usize, p1: U256) {
129 for _ in 0..pop {
130 self.data.pop();
131 }
132 self.data.push(p1);
133 }
134
135 fn unchecked_pop_push0(&mut self, pop: usize, _p1: ()) {
136 for _ in 0..pop {
137 self.data.pop();
138 }
139 }
140
141 #[inline]
145 pub fn peek(&self, no_from_top: usize) -> Result<U256, ExitException> {
146 if self.data.len() > no_from_top {
147 Ok(self.data[self.data.len() - no_from_top - 1])
148 } else {
149 Err(ExitException::StackUnderflow)
150 }
151 }
152
153 #[inline]
157 pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), ExitException> {
158 if self.data.len() > no_from_top {
159 let len = self.data.len();
160 self.data[len - no_from_top - 1] = val;
161 Ok(())
162 } else {
163 Err(ExitException::StackUnderflow)
164 }
165 }
166
167 impl_perform_popn_pushn!(perform_pop0_push1, 0, 1, (), (0), unchecked_pop_push1);
168 impl_perform_popn_pushn!(perform_pop1_push0, 1, 0, (0), (), unchecked_pop_push0);
169 impl_perform_popn_pushn!(perform_pop1_push1, 1, 1, (0), (0), unchecked_pop_push1);
170 impl_perform_popn_pushn!(perform_pop2_push1, 2, 1, (0, 1), (0), unchecked_pop_push1);
171 impl_perform_popn_pushn!(perform_pop3_push0, 3, 0, (0, 1, 2), (), unchecked_pop_push0);
172 impl_perform_popn_pushn!(
173 perform_pop4_push0,
174 4,
175 0,
176 (0, 1, 2, 3),
177 (),
178 unchecked_pop_push0
179 );
180 impl_perform_popn_pushn!(
181 perform_pop6_push0,
182 6,
183 0,
184 (0, 1, 2, 3, 4, 5),
185 (),
186 unchecked_pop_push0
187 );
188 impl_perform_popn_pushn!(
189 perform_pop7_push0,
190 7,
191 0,
192 (0, 1, 2, 3, 4, 5, 6),
193 (),
194 unchecked_pop_push0
195 );
196}