stak_file/
primitive_set.rs

1mod primitive;
2
3pub use self::primitive::Primitive;
4use crate::FileSystem;
5use stak_vm::{Error, Memory, Number, PrimitiveSet};
6
7/// A primitive set for a file system.
8pub struct FilePrimitiveSet<T: FileSystem> {
9    file_system: T,
10}
11
12impl<T: FileSystem> FilePrimitiveSet<T> {
13    /// Creates a primitive set.
14    pub const fn new(file_system: T) -> Self {
15        Self { file_system }
16    }
17
18    fn operate_result<'a, E>(
19        memory: &mut Memory<'a>,
20        mut operate: impl FnMut(&mut Memory<'a>) -> Result<(), E>,
21    ) -> Result<(), Error> {
22        let result = operate(memory);
23        memory.push(memory.boolean(result.is_ok()).into())?;
24        Ok(())
25    }
26}
27
28impl<T: FileSystem> PrimitiveSet for FilePrimitiveSet<T> {
29    type Error = Error;
30
31    fn operate(&mut self, memory: &mut Memory, primitive: usize) -> Result<(), Self::Error> {
32        match primitive {
33            Primitive::OPEN_FILE => memory.operate_option(|memory| {
34                let [list, output] = memory.pop_many();
35                let path = T::decode_path(memory, list).ok()?;
36                let output = output != memory.boolean(false).into();
37
38                self.file_system
39                    .open(path.as_ref(), output)
40                    .ok()
41                    .map(|descriptor| Number::new(descriptor as _).into())
42            })?,
43            Primitive::CLOSE_FILE => Self::operate_result(memory, |memory| {
44                let [descriptor] = memory.pop_numbers();
45
46                self.file_system.close(descriptor.to_i64() as _)
47            })?,
48            Primitive::READ_FILE => memory.operate_option(|memory| {
49                let [descriptor] = memory.pop_numbers();
50
51                self.file_system
52                    .read(descriptor.to_i64() as _)
53                    .ok()
54                    .map(|byte| Number::new(byte as _).into())
55            })?,
56            Primitive::WRITE_FILE => Self::operate_result(memory, |memory| {
57                let [descriptor, byte] = memory.pop_numbers();
58
59                self.file_system
60                    .write(descriptor.to_i64() as _, byte.to_i64() as _)
61            })?,
62            Primitive::DELETE_FILE => memory.operate_option(|memory| {
63                let [list] = memory.pop_many();
64                let path = T::decode_path(memory, list).ok()?;
65
66                self.file_system
67                    .delete(path.as_ref())
68                    .ok()
69                    .map(|_| memory.boolean(true).into())
70            })?,
71            Primitive::EXISTS_FILE => memory.operate_option(|memory| {
72                let [list] = memory.pop_many();
73                let path = T::decode_path(memory, list).ok()?;
74
75                self.file_system
76                    .exists(path.as_ref())
77                    .ok()
78                    .map(|value| memory.boolean(value).into())
79            })?,
80            _ => return Err(Error::IllegalPrimitive),
81        }
82
83        Ok(())
84    }
85}