wasmer_interface_types/interpreter/
stack.rs

1//! A very light and generic stack implementation, exposing only the
2//! operations required by the interpreter.
3
4/// The `Stackable` trait represents a small basic set of operations
5/// required by the interpreter.
6pub trait Stackable {
7    /// The kind of item the stack holds.
8    type Item;
9
10    /// Checks whether the stack is empty.
11    fn is_empty(&self) -> bool;
12
13    /// Extracts a slice containing the entire stack.
14    fn as_slice(&self) -> &[Self::Item];
15
16    /// Appends one item to the end of the stack.
17    fn push(&mut self, item: Self::Item);
18
19    /// Removes the last item of the stack and returns it, `None` if
20    /// the stack is empty.
21    fn pop1(&mut self) -> Option<Self::Item>;
22
23    /// Removes `n` elements from the end of the stack, `None` if the
24    /// stack doesn't contain enough elements.
25    /// Returned items are in reverse order: the last element comes
26    /// last in the list.
27    fn pop(&mut self, n: usize) -> Option<Vec<Self::Item>>;
28
29    /// Peek the last item of the stack and returns a reference to it,
30    /// `None` if the stack is empty.
31    fn peek1(&self) -> Option<&Self::Item>;
32}
33
34/// A stack implementation of the `Stackable` trait, based on a vector.
35#[derive(Debug, Default)]
36pub struct Stack<T>
37where
38    T: Default + Clone,
39{
40    /// Inner structure holding the items.
41    inner: Vec<T>,
42}
43
44impl<T> Stack<T>
45where
46    T: Default + Clone,
47{
48    /// Creates a new empty stack.
49    pub fn new() -> Self {
50        Self {
51            ..Default::default()
52        }
53    }
54}
55
56impl<T> Stackable for Stack<T>
57where
58    T: Default + Clone,
59{
60    type Item = T;
61
62    fn is_empty(&self) -> bool {
63        self.inner.is_empty()
64    }
65
66    fn as_slice(&self) -> &[Self::Item] {
67        self.inner.as_slice()
68    }
69
70    fn push(&mut self, item: Self::Item) {
71        self.inner.push(item);
72    }
73
74    fn pop1(&mut self) -> Option<Self::Item> {
75        self.inner.pop()
76    }
77
78    fn pop(&mut self, n: usize) -> Option<Vec<Self::Item>> {
79        if self.inner.len() < n {
80            None
81        } else {
82            let items = self
83                .inner
84                .drain(self.inner.len() - n..)
85                .collect::<Vec<Self::Item>>();
86
87            assert!(items.len() == n);
88
89            Some(items)
90        }
91    }
92
93    fn peek1(&self) -> Option<&Self::Item> {
94        if self.inner.is_empty() {
95            None
96        } else {
97            Some(&self.inner[self.inner.len() - 1])
98        }
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::{Stack, Stackable};
105
106    #[test]
107    fn test_is_empty() {
108        let mut stack = Stack::new();
109        assert_eq!(stack.is_empty(), true);
110
111        stack.push(1);
112        assert_eq!(stack.is_empty(), false);
113    }
114
115    #[test]
116    fn test_push_pop1() {
117        let mut stack = Stack::new();
118        stack.push(1);
119
120        assert_eq!(stack.pop1(), Some(1));
121        assert_eq!(stack.is_empty(), true);
122    }
123
124    #[test]
125    fn test_pop() {
126        let mut stack = Stack::new();
127        stack.push(1);
128        stack.push(2);
129        stack.push(3);
130        stack.push(4);
131        stack.push(5);
132        stack.push(6);
133
134        assert_eq!(stack.pop(1), Some(vec![6]));
135        assert_eq!(stack.pop(2), Some(vec![4, 5]));
136        assert_eq!(stack.pop(4), None); // not enough items
137        assert_eq!(stack.pop(3), Some(vec![1, 2, 3]));
138        assert_eq!(stack.pop1(), None);
139        assert_eq!(stack.is_empty(), true);
140    }
141
142    #[test]
143    fn test_peek1() {
144        let mut stack = Stack::new();
145        stack.push(1);
146        stack.push(2);
147
148        assert_eq!(stack.peek1(), Some(&2));
149    }
150}