1use crate::prelude::Vec;
2use crate::utils::USIZE_MAX;
3use crate::ExitError;
4use primitive_types::{H256, U256};
5
6#[derive(Clone, Debug)]
8pub struct Stack {
9 data: Vec<U256>,
10 limit: usize,
11}
12
13impl Stack {
14 #[must_use]
16 pub const fn new(limit: usize) -> Self {
17 Self {
18 data: Vec::new(),
19 limit,
20 }
21 }
22
23 #[inline]
25 #[must_use]
26 pub const fn limit(&self) -> usize {
27 self.limit
28 }
29
30 #[inline]
32 #[must_use]
33 #[allow(clippy::missing_const_for_fn)]
35 pub fn len(&self) -> usize {
36 self.data.len()
37 }
38
39 #[inline]
41 #[must_use]
42 #[allow(clippy::missing_const_for_fn)]
44 pub fn is_empty(&self) -> bool {
45 self.data.is_empty()
46 }
47
48 #[inline]
50 #[must_use]
51 pub const fn data(&self) -> &Vec<U256> {
52 &self.data
53 }
54
55 #[inline]
61 pub fn pop(&mut self) -> Result<U256, ExitError> {
62 self.data.pop().ok_or(ExitError::StackUnderflow)
63 }
64
65 #[inline]
68 pub fn pop_h256(&mut self) -> Result<H256, ExitError> {
69 self.pop().map(|it| H256(it.to_big_endian()))
70 }
71
72 #[inline]
78 pub fn push(&mut self, value: U256) -> Result<(), ExitError> {
79 if self.data.len() + 1 > self.limit {
80 return Err(ExitError::StackOverflow);
81 }
82 self.data.push(value);
83 Ok(())
84 }
85
86 #[inline]
93 pub fn peek(&self, no_from_top: usize) -> Result<U256, ExitError> {
94 if self.data.len() > no_from_top {
95 Ok(self.data[self.data.len() - no_from_top - 1])
96 } else {
97 Err(ExitError::StackUnderflow)
98 }
99 }
100
101 #[inline]
102 pub fn peek_h256(&self, no_from_top: usize) -> Result<H256, ExitError> {
109 self.peek(no_from_top).map(|it| H256(it.to_big_endian()))
110 }
111
112 #[inline]
119 pub fn peek_usize(&self, no_from_top: usize) -> Result<usize, ExitError> {
120 let u = self.peek(no_from_top)?;
121 if u > USIZE_MAX {
122 return Err(ExitError::OutOfGas);
123 }
124 Ok(u.as_usize())
125 }
126
127 #[inline]
134 pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), ExitError> {
135 if self.data.len() > no_from_top {
136 let len = self.data.len();
137 self.data[len - no_from_top - 1] = val;
138 Ok(())
139 } else {
140 Err(ExitError::StackUnderflow)
141 }
142 }
143}