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}