oak_vfs/vfs/
memory.rs

1use crate::{FileMetadata, FileType, Vfs, WritableVfs};
2use oak_core::source::SourceText;
3use std::{
4    collections::HashMap,
5    sync::{Arc, RwLock},
6};
7
8/// A memory-based Virtual File System implementation.
9/// Ideal for WASM environments or testing where physical disk access is not available.
10#[derive(Default, Clone)]
11pub struct MemoryVfs {
12    files: Arc<RwLock<HashMap<String, FileEntry>>>,
13}
14
15struct FileEntry {
16    content: String,
17    modified: u64,
18}
19
20impl MemoryVfs {
21    /// Create a new empty MemoryVfs.
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Upsert a file's content in the memory VFS.
27    pub fn write_file(&self, uri: &str, content: String) {
28        let mut files = self.files.write().unwrap();
29        files.insert(uri.to_string(), FileEntry { content, modified: Self::now() });
30    }
31
32    /// Remove a file from the memory VFS.
33    pub fn remove_file(&self, uri: &str) {
34        let mut files = self.files.write().unwrap();
35        files.remove(uri);
36    }
37
38    fn now() -> u64 {
39        // In WASM, we'd typically use js-sys::Date::now()
40        // Here we use a simple timestamp or 0 if not available
41        #[cfg(not(target_arch = "wasm32"))]
42        {
43            std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs()
44        }
45        #[cfg(target_arch = "wasm32")]
46        {
47            0 // Simplified for now
48        }
49    }
50}
51
52impl Vfs for MemoryVfs {
53    type Source = SourceText;
54
55    fn get_source(&self, uri: &str) -> Option<SourceText> {
56        let files = self.files.read().unwrap();
57        files.get(uri).map(|entry| SourceText::new(entry.content.clone()))
58    }
59
60    fn exists(&self, uri: &str) -> bool {
61        self.files.read().unwrap().contains_key(uri)
62    }
63
64    fn metadata(&self, uri: &str) -> Option<FileMetadata> {
65        let files = self.files.read().unwrap();
66        files.get(uri).map(|entry| FileMetadata { file_type: FileType::File, len: entry.content.len() as u64, modified: Some(entry.modified) })
67    }
68
69    fn read_dir(&self, _uri: &str) -> Option<Vec<String>> {
70        // Basic implementation: return all keys for now
71        // A more complex one would handle directory hierarchy
72        let files = self.files.read().unwrap();
73        Some(files.keys().cloned().collect())
74    }
75}
76
77impl WritableVfs for MemoryVfs {
78    fn write_file(&self, uri: &str, content: String) {
79        self.write_file(uri, content);
80    }
81
82    fn remove_file(&self, uri: &str) {
83        self.remove_file(uri);
84    }
85}