stak_file/
primitive_set.rs

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