wasmi_validation/
stack.rs

1use 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/// Stack with limit.
24#[derive(Debug)]
25pub struct StackWithLimit<T>
26where
27    T: Clone,
28{
29    /// Stack values.
30    values: Vec<T>,
31    /// Stack limit (maximal stack len).
32    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}