stak_file/file_system/
memory.rs

1use super::utility::decode_path;
2use crate::{FileDescriptor, FileError, FileSystem};
3use heapless::Vec;
4use stak_vm::{Memory, Value};
5
6const PATH_SIZE: usize = 128;
7
8#[derive(Clone, Copy, Debug)]
9pub struct MemoryFileEntry {
10    file_index: usize,
11    offset: usize,
12}
13
14/// A in-memory file system.
15#[derive(Debug)]
16pub struct MemoryFileSystem<'a> {
17    files: &'a [(&'a [u8], &'a [u8])],
18    entries: &'a mut [Option<MemoryFileEntry>],
19}
20
21impl<'a> MemoryFileSystem<'a> {
22    /// Creates a file system.
23    pub const fn new(
24        files: &'a [(&'a [u8], &'a [u8])],
25        entries: &'a mut [Option<MemoryFileEntry>],
26    ) -> Self {
27        Self { files, entries }
28    }
29}
30
31impl FileSystem for MemoryFileSystem<'_> {
32    type Path = [u8];
33    type PathBuf = Vec<u8, PATH_SIZE>;
34    type Error = FileError;
35
36    fn open(&mut self, path: &Self::Path, output: bool) -> Result<FileDescriptor, Self::Error> {
37        if output {
38            return Err(FileError::Open);
39        }
40
41        for (file_index, (file_path, _)) in self.files.iter().enumerate() {
42            if path == *file_path {
43                for (descriptor, entry) in self.entries.iter_mut().enumerate() {
44                    if entry.is_none() {
45                        *entry = Some(MemoryFileEntry {
46                            file_index,
47                            offset: 0,
48                        });
49
50                        return Ok(descriptor);
51                    }
52                }
53            }
54        }
55
56        Err(FileError::Open)
57    }
58
59    fn close(&mut self, descriptor: FileDescriptor) -> Result<(), Self::Error> {
60        let Some(entry) = self.entries.get_mut(descriptor) else {
61            return Err(FileError::Close);
62        };
63
64        *entry = None;
65
66        Ok(())
67    }
68
69    fn read(&mut self, descriptor: FileDescriptor) -> Result<Option<u8>, Self::Error> {
70        let entry = &mut self
71            .entries
72            .get_mut(descriptor)
73            .and_then(Option::as_mut)
74            .ok_or(FileError::Read)?;
75
76        let Some(&byte) = self
77            .files
78            .get(entry.file_index)
79            .ok_or(FileError::Read)?
80            .1
81            .get(entry.offset)
82        else {
83            return Ok(None);
84        };
85
86        entry.offset += 1;
87
88        Ok(Some(byte))
89    }
90
91    fn write(&mut self, _: FileDescriptor, _: u8) -> Result<(), Self::Error> {
92        Err(FileError::Write)
93    }
94
95    fn delete(&mut self, _: &Self::Path) -> Result<(), Self::Error> {
96        Err(FileError::Delete)
97    }
98
99    fn flush(&mut self, _: FileDescriptor) -> Result<(), Self::Error> {
100        Err(FileError::Flush)
101    }
102
103    fn exists(&self, path: &Self::Path) -> Result<bool, Self::Error> {
104        for (file_path, _) in self.files {
105            if &path == file_path {
106                return Ok(true);
107            }
108        }
109
110        Ok(false)
111    }
112
113    fn decode_path(memory: &Memory, list: Value) -> Result<Self::PathBuf, Self::Error> {
114        decode_path(memory, list).ok_or(FileError::PathDecode)
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn create_file_system() {
124        MemoryFileSystem::new(&[], &mut []);
125    }
126
127    #[test]
128    fn read() {
129        let mut entries = [Default::default(); 8];
130        let mut system = MemoryFileSystem::new(&[(b"foo", b"bar")], &mut entries);
131
132        let descriptor = system.open(b"foo", false).unwrap();
133
134        assert_eq!(system.read(descriptor), Ok(Some(b'b')));
135        assert_eq!(system.read(descriptor), Ok(Some(b'a')));
136        assert_eq!(system.read(descriptor), Ok(Some(b'r')));
137        assert_eq!(system.read(descriptor), Ok(None));
138
139        system.close(descriptor).unwrap();
140
141        assert!(system.read(descriptor).is_err());
142    }
143
144    #[test]
145    fn exists() {
146        let mut entries = [Default::default(); 8];
147        let system = MemoryFileSystem::new(&[(b"foo", b"bar")], &mut entries);
148
149        assert!(system.exists(b"foo").unwrap());
150        assert!(!system.exists(b"bar").unwrap());
151    }
152}