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