stak_file/
primitive_set.rs1mod 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
9pub struct FilePrimitiveSet<T: FileSystem> {
11 file_system: T,
12}
13
14impl<T: FileSystem> FilePrimitiveSet<T> {
15 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}