stak_file/
primitive_set.rs1mod primitive;
2
3pub use self::primitive::Primitive;
4use crate::FileSystem;
5use stak_vm::{Error, Memory, Number, PrimitiveSet};
6
7pub struct FilePrimitiveSet<T: FileSystem> {
9 file_system: T,
10}
11
12impl<T: FileSystem> FilePrimitiveSet<T> {
13 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}