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