xwasmi_validation/
stack.rs

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