zephyr_vm/
stack.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! This module defines the pseudo stack implementation
//! that is used in Zephyr for the guest environment
//! to provide instructions to host environment.

use crate::{error::HostError, ZephyrStandard};
use anyhow::Result;
use std::{borrow::BorrowMut, cell::RefCell, rc::Rc};

/// Stack implementation.
#[derive(Clone)]
pub struct StackImpl {
    /// Inner stack vector.
    pub inner: RefCell<Vec<i64>>,
    step: RefCell<usize>,
}

/// Stack implementation wrapper.
#[derive(Clone)]
pub struct Stack(pub Rc<StackImpl>);

impl ZephyrStandard for StackImpl {
    fn zephyr_standard() -> Result<Self> {
        Ok(Self {
            inner: RefCell::new(Vec::new()),
            step: RefCell::new(0),
        })
    }
}

impl StackImpl {
    /// Pushes a value to the stack.
    pub fn push(&self, val: i64) {
        let mut stack = self.inner.borrow_mut();
        stack.borrow_mut().push(val);
    }

    /// Clear the stack.
    pub fn clear(&self) {
        let mut stack = self.inner.borrow_mut();
        *self.step.borrow_mut() = 0;
        stack.borrow_mut().clear();
    }

    /// Load a mutable reference to the stack.
    pub fn load_host(&self) -> &RefCell<Vec<i64>> {
        &self.inner
    }

    /// Load the cloned stack.
    pub fn load(&self) -> Vec<i64> {
        self.inner.borrow().clone()
    }

    /// Reads the current value on stack and increments
    /// the count.
    pub fn get_with_step(&self) -> Result<i64, HostError> {
        let current = self.step.clone().into_inner();
        *self.step.borrow_mut() = current + 1;

        self.inner
            .borrow()
            .get(current)
            .copied()
            .ok_or(HostError::NoValOnStack)
    }

    /// Returns the current count.
    pub fn get_current_step(&self) -> usize {
        self.step.clone().into_inner()
    }
}

impl ZephyrStandard for Stack {
    fn zephyr_standard() -> Result<Self> {
        Ok(Self(Rc::new(StackImpl::zephyr_standard()?)))
    }
}