Skip to main content

stack_assembly/
operand_stack.rs

1use crate::{Effect, Value};
2
3/// # The operand stack
4///
5/// StackAssembly's evaluation model is based on an implicit stack which
6/// stores all operands.
7///
8/// Aside from this, the stack is an important communication channel between
9/// script and host. Please refer to [`Eval`]'s [`operand_stack`] field for more
10/// information on that.
11///
12/// [`Eval`]: crate::Eval
13/// [`operand_stack`]: struct.Eval.html#structfield.operand_stack
14#[derive(Debug, Default)]
15pub struct OperandStack {
16    /// # The values on the stack
17    pub values: Vec<Value>,
18}
19
20impl OperandStack {
21    /// # Push a value to the top of the stack
22    pub fn push(&mut self, value: impl Into<Value>) {
23        self.values.push(value.into());
24    }
25
26    /// # Pop a value from the top of the stack
27    ///
28    /// Return [`OperandStackUnderflow`], if no value is available on the stack,
29    /// which provides an automatic conversion to [`Effect`].
30    pub fn pop(&mut self) -> Result<Value, OperandStackUnderflow> {
31        self.values.pop().ok_or(OperandStackUnderflow)
32    }
33
34    /// # Access the stack as a slice of `i32` values
35    pub fn to_i32_slice(&self) -> &[i32] {
36        bytemuck::cast_slice(&self.values)
37    }
38
39    /// # Access the stack as a slice of `u32` values
40    pub fn to_u32_slice(&self) -> &[u32] {
41        bytemuck::cast_slice(&self.values)
42    }
43}
44
45/// # Tried to pop a value from an empty stack
46///
47/// See [`OperandStack::pop`].
48#[derive(Debug)]
49pub struct OperandStackUnderflow;
50
51impl From<OperandStackUnderflow> for Effect {
52    fn from(OperandStackUnderflow: OperandStackUnderflow) -> Self {
53        Effect::OperandStackUnderflow
54    }
55}