wasmi_validation/
stack.rs1use alloc::{string::String, vec::Vec};
2
3use core::fmt;
4#[cfg(feature = "std")]
5use std::error;
6
7#[derive(Debug)]
8pub struct Error(String);
9
10impl fmt::Display for Error {
11 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12 write!(f, "{}", self.0)
13 }
14}
15
16#[cfg(feature = "std")]
17impl error::Error for Error {
18 fn description(&self) -> &str {
19 &self.0
20 }
21}
22
23#[derive(Debug)]
25pub struct StackWithLimit<T>
26where
27 T: Clone,
28{
29 values: Vec<T>,
31 limit: usize,
33}
34
35impl<T> StackWithLimit<T>
36where
37 T: Clone,
38{
39 pub fn with_limit(limit: usize) -> Self {
40 StackWithLimit {
41 values: Vec::new(),
42 limit,
43 }
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.values.is_empty()
48 }
49
50 pub fn len(&self) -> usize {
51 self.values.len()
52 }
53
54 pub fn top(&self) -> Result<&T, Error> {
55 self.values
56 .last()
57 .ok_or_else(|| Error("non-empty stack expected".into()))
58 }
59
60 pub fn top_mut(&mut self) -> Result<&mut T, Error> {
61 self.values
62 .last_mut()
63 .ok_or_else(|| Error("non-empty stack expected".into()))
64 }
65
66 pub fn get(&self, index: usize) -> Result<&T, Error> {
67 if index >= self.values.len() {
68 return Err(Error(format!(
69 "trying to get value at position {} on stack of size {}",
70 index,
71 self.values.len()
72 )));
73 }
74
75 Ok(self
76 .values
77 .get(self.values.len() - 1 - index)
78 .expect("checked couple of lines above"))
79 }
80
81 pub fn push(&mut self, value: T) -> Result<(), Error> {
82 if self.values.len() >= self.limit {
83 return Err(Error(format!("exceeded stack limit {}", self.limit)));
84 }
85
86 self.values.push(value);
87 Ok(())
88 }
89
90 pub fn pop(&mut self) -> Result<T, Error> {
91 self.values
92 .pop()
93 .ok_or_else(|| Error("non-empty stack expected".into()))
94 }
95
96 pub fn resize(&mut self, new_size: usize, dummy: T) {
97 debug_assert!(new_size <= self.values.len());
98 self.values.resize(new_size, dummy);
99 }
100}