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(
54 if let Some(byte) = self
55 .file_system
56 .read(descriptor.to_i64() as _)
57 .map_err(|_| FileError::Read)?
58 {
59 Number::from_i64(byte as _).into()
60 } else {
61 memory.boolean(false)?.into()
62 },
63 )?;
64 }
65 Primitive::WRITE_FILE => {
66 let [descriptor, byte] = memory.pop_numbers()?;
67
68 self.file_system
69 .write(descriptor.to_i64() as _, byte.to_i64() as _)
70 .map_err(|_| FileError::Write)?;
71
72 memory.push(memory.boolean(false)?.into())?;
73 }
74 Primitive::DELETE_FILE => {
75 let [list] = memory.pop_many()?;
76 let path = T::decode_path(memory, list).map_err(|_| FileError::PathDecode)?;
77
78 self.file_system
79 .delete(path.as_ref())
80 .map_err(|_| FileError::Delete)?;
81
82 memory.push(memory.boolean(false)?.into())?;
83 }
84 Primitive::EXISTS_FILE => {
85 let [list] = memory.pop_many()?;
86 let path = T::decode_path(memory, list).map_err(|_| FileError::PathDecode)?;
87
88 memory.push(
89 memory
90 .boolean(
91 self.file_system
92 .exists(path.as_ref())
93 .map_err(|_| FileError::Exists)?,
94 )?
95 .into(),
96 )?;
97 }
98 Primitive::FLUSH_FILE => {
99 let [descriptor] = memory.pop_numbers()?;
100
101 self.file_system
102 .flush(descriptor.to_i64() as _)
103 .map_err(|_| FileError::Flush)?;
104
105 memory.push(memory.boolean(false)?.into())?;
106 }
107 _ => return Err(Error::IllegalPrimitive.into()),
108 }
109
110 Ok(())
111 }
112}