stak_device/
primitive_set.rs

1mod error;
2mod primitive;
3
4pub use self::{error::PrimitiveError, primitive::Primitive};
5use crate::Device;
6use stak_vm::{Memory, Number, PrimitiveSet};
7use winter_maybe_async::{maybe_async, maybe_await};
8
9/// A primitive set for a device.
10pub struct DevicePrimitiveSet<T: Device> {
11    device: T,
12}
13
14impl<T: Device> DevicePrimitiveSet<T> {
15    /// Creates a primitive set.
16    pub const fn new(device: T) -> Self {
17        Self { device }
18    }
19
20    /// Returns a reference to a device.
21    pub const fn device(&self) -> &T {
22        &self.device
23    }
24
25    /// Returns a mutable reference to a device.
26    pub const fn device_mut(&mut self) -> &mut T {
27        &mut self.device
28    }
29}
30
31impl<T: Device> PrimitiveSet for DevicePrimitiveSet<T> {
32    type Error = PrimitiveError;
33
34    #[maybe_async]
35    fn operate(&mut self, memory: &mut Memory<'_>, primitive: usize) -> Result<(), Self::Error> {
36        match primitive {
37            Primitive::READ => {
38                let byte =
39                    maybe_await!(self.device.read()).map_err(|_| PrimitiveError::ReadInput)?;
40
41                memory.push(if let Some(byte) = byte {
42                    Number::from_i64(byte as _).into()
43                } else {
44                    memory.boolean(false)?.into()
45                })?;
46            }
47            Primitive::WRITE => {
48                let byte = memory.pop()?.assume_number().to_i64() as u8;
49                maybe_await!(self.device.write(byte)).map_err(|_| PrimitiveError::WriteOutput)?;
50                memory.push(memory.boolean(false)?.into())?;
51            }
52            Primitive::WRITE_ERROR => {
53                let byte = memory.pop()?.assume_number().to_i64() as u8;
54                maybe_await!(self.device.write_error(byte))
55                    .map_err(|_| PrimitiveError::WriteError)?;
56                memory.push(memory.boolean(false)?.into())?;
57            }
58            _ => return Err(stak_vm::Error::IllegalPrimitive.into()),
59        }
60
61        Ok(())
62    }
63}