crabtalk_runtime/memory/
storage.rs1use anyhow::Result;
4use std::{
5 collections::HashMap,
6 path::{Path, PathBuf},
7 sync::RwLock,
8};
9
10pub trait Storage: Send + Sync {
12 fn read(&self, path: &Path) -> Result<String>;
13 fn write(&self, path: &Path, content: &str) -> Result<()>;
14 fn delete(&self, path: &Path) -> Result<()>;
15 fn list(&self, dir: &Path) -> Result<Vec<PathBuf>>;
16 fn create_dir_all(&self, path: &Path) -> Result<()>;
17 fn exists(&self, path: &Path) -> bool;
18 fn rename(&self, from: &Path, to: &Path) -> Result<()>;
19}
20
21pub struct FsStorage;
23
24impl Storage for FsStorage {
25 fn read(&self, path: &Path) -> Result<String> {
26 Ok(std::fs::read_to_string(path)?)
27 }
28
29 fn write(&self, path: &Path, content: &str) -> Result<()> {
30 Ok(std::fs::write(path, content)?)
31 }
32
33 fn delete(&self, path: &Path) -> Result<()> {
34 Ok(std::fs::remove_file(path)?)
35 }
36
37 fn list(&self, dir: &Path) -> Result<Vec<PathBuf>> {
38 let mut paths = Vec::new();
39 for entry in std::fs::read_dir(dir)? {
40 paths.push(entry?.path());
41 }
42 Ok(paths)
43 }
44
45 fn create_dir_all(&self, path: &Path) -> Result<()> {
46 Ok(std::fs::create_dir_all(path)?)
47 }
48
49 fn exists(&self, path: &Path) -> bool {
50 path.exists()
51 }
52
53 fn rename(&self, from: &Path, to: &Path) -> Result<()> {
54 Ok(std::fs::rename(from, to)?)
55 }
56}
57
58pub struct MemStorage {
60 files: RwLock<HashMap<PathBuf, String>>,
61}
62
63impl Default for MemStorage {
64 fn default() -> Self {
65 Self {
66 files: RwLock::new(HashMap::new()),
67 }
68 }
69}
70
71impl MemStorage {
72 pub fn new() -> Self {
73 Self::default()
74 }
75}
76
77impl Storage for MemStorage {
78 fn read(&self, path: &Path) -> Result<String> {
79 self.files
80 .read()
81 .unwrap()
82 .get(path)
83 .cloned()
84 .ok_or_else(|| anyhow::anyhow!("file not found: {}", path.display()))
85 }
86
87 fn write(&self, path: &Path, content: &str) -> Result<()> {
88 self.files
89 .write()
90 .unwrap()
91 .insert(path.to_path_buf(), content.to_owned());
92 Ok(())
93 }
94
95 fn delete(&self, path: &Path) -> Result<()> {
96 self.files
97 .write()
98 .unwrap()
99 .remove(path)
100 .ok_or_else(|| anyhow::anyhow!("file not found: {}", path.display()))?;
101 Ok(())
102 }
103
104 fn list(&self, dir: &Path) -> Result<Vec<PathBuf>> {
105 let files = self.files.read().unwrap();
106 Ok(files
107 .keys()
108 .filter(|p| p.parent() == Some(dir))
109 .cloned()
110 .collect())
111 }
112
113 fn create_dir_all(&self, _path: &Path) -> Result<()> {
114 Ok(())
115 }
116
117 fn exists(&self, path: &Path) -> bool {
118 self.files.read().unwrap().contains_key(path)
119 }
120
121 fn rename(&self, from: &Path, to: &Path) -> Result<()> {
122 let mut files = self.files.write().unwrap();
123 let content = files
124 .remove(from)
125 .ok_or_else(|| anyhow::anyhow!("file not found: {}", from.display()))?;
126 files.insert(to.to_path_buf(), content);
127 Ok(())
128 }
129}