cdx_core/archive/
storage.rs1use std::collections::HashMap;
8
9use crate::Result;
10
11pub trait ArchiveStorage {
17 fn read_file(&mut self, path: &str) -> Result<Vec<u8>>;
23
24 fn write_file(&mut self, path: &str, data: &[u8]) -> Result<()>;
30
31 fn file_exists(&self, path: &str) -> bool;
33
34 fn file_names(&self) -> Vec<String>;
36}
37
38#[derive(Debug, Clone, Default)]
56pub struct MemoryStorage {
57 files: HashMap<String, Vec<u8>>,
58}
59
60impl MemoryStorage {
61 #[must_use]
63 pub fn new() -> Self {
64 Self {
65 files: HashMap::new(),
66 }
67 }
68
69 #[must_use]
71 pub fn with_files(files: HashMap<String, Vec<u8>>) -> Self {
72 Self { files }
73 }
74
75 #[must_use]
77 pub fn len(&self) -> usize {
78 self.files.len()
79 }
80
81 #[must_use]
83 pub fn is_empty(&self) -> bool {
84 self.files.is_empty()
85 }
86
87 pub fn remove(&mut self, path: &str) -> Option<Vec<u8>> {
91 self.files.remove(path)
92 }
93
94 pub fn clear(&mut self) {
96 self.files.clear();
97 }
98}
99
100impl ArchiveStorage for MemoryStorage {
101 fn read_file(&mut self, path: &str) -> Result<Vec<u8>> {
102 self.files
103 .get(path)
104 .cloned()
105 .ok_or_else(|| crate::Error::MissingFile {
106 path: path.to_string(),
107 })
108 }
109
110 fn write_file(&mut self, path: &str, data: &[u8]) -> Result<()> {
111 self.files.insert(path.to_string(), data.to_vec());
112 Ok(())
113 }
114
115 fn file_exists(&self, path: &str) -> bool {
116 self.files.contains_key(path)
117 }
118
119 fn file_names(&self) -> Vec<String> {
120 self.files.keys().cloned().collect()
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn test_memory_storage_new() {
130 let storage = MemoryStorage::new();
131 assert!(storage.is_empty());
132 assert_eq!(storage.len(), 0);
133 }
134
135 #[test]
136 fn test_memory_storage_write_read() {
137 let mut storage = MemoryStorage::new();
138
139 storage.write_file("test.txt", b"Hello").unwrap();
140 assert_eq!(storage.read_file("test.txt").unwrap(), b"Hello");
141 }
142
143 #[test]
144 fn test_memory_storage_file_exists() {
145 let mut storage = MemoryStorage::new();
146
147 assert!(!storage.file_exists("test.txt"));
148 storage.write_file("test.txt", b"data").unwrap();
149 assert!(storage.file_exists("test.txt"));
150 }
151
152 #[test]
153 fn test_memory_storage_file_names() {
154 let mut storage = MemoryStorage::new();
155
156 storage.write_file("a.txt", b"a").unwrap();
157 storage.write_file("b.txt", b"b").unwrap();
158
159 let names = storage.file_names();
160 assert_eq!(names.len(), 2);
161 assert!(names.contains(&"a.txt".to_string()));
162 assert!(names.contains(&"b.txt".to_string()));
163 }
164
165 #[test]
166 fn test_memory_storage_read_missing() {
167 let mut storage = MemoryStorage::new();
168 let result = storage.read_file("nonexistent");
169 assert!(result.is_err());
170 }
171
172 #[test]
173 fn test_memory_storage_overwrite() {
174 let mut storage = MemoryStorage::new();
175
176 storage.write_file("test.txt", b"first").unwrap();
177 storage.write_file("test.txt", b"second").unwrap();
178
179 assert_eq!(storage.read_file("test.txt").unwrap(), b"second");
180 assert_eq!(storage.len(), 1);
181 }
182
183 #[test]
184 fn test_memory_storage_remove() {
185 let mut storage = MemoryStorage::new();
186
187 storage.write_file("test.txt", b"data").unwrap();
188 let removed = storage.remove("test.txt");
189
190 assert_eq!(removed, Some(b"data".to_vec()));
191 assert!(!storage.file_exists("test.txt"));
192 }
193
194 #[test]
195 fn test_memory_storage_remove_nonexistent() {
196 let mut storage = MemoryStorage::new();
197 assert!(storage.remove("nonexistent").is_none());
198 }
199
200 #[test]
201 fn test_memory_storage_clear() {
202 let mut storage = MemoryStorage::new();
203
204 storage.write_file("a.txt", b"a").unwrap();
205 storage.write_file("b.txt", b"b").unwrap();
206 storage.clear();
207
208 assert!(storage.is_empty());
209 }
210
211 #[test]
212 fn test_memory_storage_with_files() {
213 let mut files = HashMap::new();
214 files.insert("existing.txt".to_string(), b"content".to_vec());
215
216 let mut storage = MemoryStorage::with_files(files);
217
218 assert!(storage.file_exists("existing.txt"));
219 assert_eq!(storage.read_file("existing.txt").unwrap(), b"content");
220 }
221
222 #[test]
223 fn test_memory_storage_binary_data() {
224 let mut storage = MemoryStorage::new();
225 let binary = vec![0x00, 0xFF, 0x7F, 0x80, 0x01];
226
227 storage.write_file("binary.dat", &binary).unwrap();
228 assert_eq!(storage.read_file("binary.dat").unwrap(), binary);
229 }
230
231 #[test]
232 fn test_memory_storage_empty_file() {
233 let mut storage = MemoryStorage::new();
234
235 storage.write_file("empty.txt", b"").unwrap();
236
237 assert!(storage.file_exists("empty.txt"));
238 assert!(storage.read_file("empty.txt").unwrap().is_empty());
239 }
240
241 #[test]
242 fn test_memory_storage_nested_paths() {
243 let mut storage = MemoryStorage::new();
244
245 storage
246 .write_file("path/to/nested/file.txt", b"nested")
247 .unwrap();
248
249 assert!(storage.file_exists("path/to/nested/file.txt"));
250 assert_eq!(
251 storage.read_file("path/to/nested/file.txt").unwrap(),
252 b"nested"
253 );
254 }
255}