1use anyfs_backend::*;
10use std::collections::HashMap;
11use std::io::{Read, Write};
12use std::path::{Path, PathBuf};
13use std::sync::atomic::{AtomicUsize, Ordering};
14use std::sync::RwLock;
15use std::time::SystemTime;
16
17struct LoggingLayer;
23
24struct LoggingFs<B> {
26 inner: B,
27 prefix: String,
28}
29
30impl<B: Fs> Layer<B> for LoggingLayer {
31 type Backend = LoggingFs<B>;
32
33 fn layer(self, inner: B) -> Self::Backend {
34 LoggingFs {
35 inner,
36 prefix: "[LOG]".to_string(),
37 }
38 }
39}
40
41impl<B: FsRead> FsRead for LoggingFs<B> {
42 fn read(&self, path: &Path) -> Result<Vec<u8>, FsError> {
43 println!("{} read({})", self.prefix, path.display());
44 let result = self.inner.read(path);
45 println!(
46 "{} read({}) -> {:?}",
47 self.prefix,
48 path.display(),
49 result.as_ref().map(|d| format!("{} bytes", d.len()))
50 );
51 result
52 }
53
54 fn read_to_string(&self, path: &Path) -> Result<String, FsError> {
55 println!("{} read_to_string({})", self.prefix, path.display());
56 self.inner.read_to_string(path)
57 }
58
59 fn read_range(&self, path: &Path, offset: u64, len: usize) -> Result<Vec<u8>, FsError> {
60 println!(
61 "{} read_range({}, {}, {})",
62 self.prefix,
63 path.display(),
64 offset,
65 len
66 );
67 self.inner.read_range(path, offset, len)
68 }
69
70 fn exists(&self, path: &Path) -> Result<bool, FsError> {
71 println!("{} exists({})", self.prefix, path.display());
72 self.inner.exists(path)
73 }
74
75 fn metadata(&self, path: &Path) -> Result<Metadata, FsError> {
76 println!("{} metadata({})", self.prefix, path.display());
77 self.inner.metadata(path)
78 }
79
80 fn open_read(&self, path: &Path) -> Result<Box<dyn Read + Send>, FsError> {
81 println!("{} open_read({})", self.prefix, path.display());
82 self.inner.open_read(path)
83 }
84}
85
86impl<B: FsWrite> FsWrite for LoggingFs<B> {
87 fn write(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
88 println!(
89 "{} write({}, {} bytes)",
90 self.prefix,
91 path.display(),
92 data.len()
93 );
94 self.inner.write(path, data)
95 }
96
97 fn append(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
98 println!(
99 "{} append({}, {} bytes)",
100 self.prefix,
101 path.display(),
102 data.len()
103 );
104 self.inner.append(path, data)
105 }
106
107 fn remove_file(&self, path: &Path) -> Result<(), FsError> {
108 println!("{} remove_file({})", self.prefix, path.display());
109 self.inner.remove_file(path)
110 }
111
112 fn rename(&self, from: &Path, to: &Path) -> Result<(), FsError> {
113 println!(
114 "{} rename({} -> {})",
115 self.prefix,
116 from.display(),
117 to.display()
118 );
119 self.inner.rename(from, to)
120 }
121
122 fn copy(&self, from: &Path, to: &Path) -> Result<(), FsError> {
123 println!(
124 "{} copy({} -> {})",
125 self.prefix,
126 from.display(),
127 to.display()
128 );
129 self.inner.copy(from, to)
130 }
131
132 fn truncate(&self, path: &Path, size: u64) -> Result<(), FsError> {
133 println!("{} truncate({}, {})", self.prefix, path.display(), size);
134 self.inner.truncate(path, size)
135 }
136
137 fn open_write(&self, path: &Path) -> Result<Box<dyn Write + Send>, FsError> {
138 println!("{} open_write({})", self.prefix, path.display());
139 self.inner.open_write(path)
140 }
141}
142
143impl<B: FsDir> FsDir for LoggingFs<B> {
144 fn read_dir(&self, path: &Path) -> Result<ReadDirIter, FsError> {
145 println!("{} read_dir({})", self.prefix, path.display());
146 self.inner.read_dir(path)
147 }
148
149 fn create_dir(&self, path: &Path) -> Result<(), FsError> {
150 println!("{} create_dir({})", self.prefix, path.display());
151 self.inner.create_dir(path)
152 }
153
154 fn create_dir_all(&self, path: &Path) -> Result<(), FsError> {
155 println!("{} create_dir_all({})", self.prefix, path.display());
156 self.inner.create_dir_all(path)
157 }
158
159 fn remove_dir(&self, path: &Path) -> Result<(), FsError> {
160 println!("{} remove_dir({})", self.prefix, path.display());
161 self.inner.remove_dir(path)
162 }
163
164 fn remove_dir_all(&self, path: &Path) -> Result<(), FsError> {
165 println!("{} remove_dir_all({})", self.prefix, path.display());
166 self.inner.remove_dir_all(path)
167 }
168}
169
170struct MetricsLayer;
176
177struct MetricsFs<B> {
179 inner: B,
180 reads: AtomicUsize,
181 writes: AtomicUsize,
182 deletes: AtomicUsize,
183}
184
185impl<B> MetricsFs<B> {
186 fn stats(&self) -> (usize, usize, usize) {
187 (
188 self.reads.load(Ordering::Relaxed),
189 self.writes.load(Ordering::Relaxed),
190 self.deletes.load(Ordering::Relaxed),
191 )
192 }
193}
194
195impl<B: Fs> Layer<B> for MetricsLayer {
196 type Backend = MetricsFs<B>;
197
198 fn layer(self, inner: B) -> Self::Backend {
199 MetricsFs {
200 inner,
201 reads: AtomicUsize::new(0),
202 writes: AtomicUsize::new(0),
203 deletes: AtomicUsize::new(0),
204 }
205 }
206}
207
208impl<B: FsRead> FsRead for MetricsFs<B> {
209 fn read(&self, path: &Path) -> Result<Vec<u8>, FsError> {
210 self.reads.fetch_add(1, Ordering::Relaxed);
211 self.inner.read(path)
212 }
213
214 fn read_to_string(&self, path: &Path) -> Result<String, FsError> {
215 self.reads.fetch_add(1, Ordering::Relaxed);
216 self.inner.read_to_string(path)
217 }
218
219 fn read_range(&self, path: &Path, offset: u64, len: usize) -> Result<Vec<u8>, FsError> {
220 self.reads.fetch_add(1, Ordering::Relaxed);
221 self.inner.read_range(path, offset, len)
222 }
223
224 fn exists(&self, path: &Path) -> Result<bool, FsError> {
225 self.inner.exists(path)
226 }
227
228 fn metadata(&self, path: &Path) -> Result<Metadata, FsError> {
229 self.inner.metadata(path)
230 }
231
232 fn open_read(&self, path: &Path) -> Result<Box<dyn Read + Send>, FsError> {
233 self.reads.fetch_add(1, Ordering::Relaxed);
234 self.inner.open_read(path)
235 }
236}
237
238impl<B: FsWrite> FsWrite for MetricsFs<B> {
239 fn write(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
240 self.writes.fetch_add(1, Ordering::Relaxed);
241 self.inner.write(path, data)
242 }
243
244 fn append(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
245 self.writes.fetch_add(1, Ordering::Relaxed);
246 self.inner.append(path, data)
247 }
248
249 fn remove_file(&self, path: &Path) -> Result<(), FsError> {
250 self.deletes.fetch_add(1, Ordering::Relaxed);
251 self.inner.remove_file(path)
252 }
253
254 fn rename(&self, from: &Path, to: &Path) -> Result<(), FsError> {
255 self.inner.rename(from, to)
256 }
257
258 fn copy(&self, from: &Path, to: &Path) -> Result<(), FsError> {
259 self.writes.fetch_add(1, Ordering::Relaxed);
260 self.inner.copy(from, to)
261 }
262
263 fn truncate(&self, path: &Path, size: u64) -> Result<(), FsError> {
264 self.writes.fetch_add(1, Ordering::Relaxed);
265 self.inner.truncate(path, size)
266 }
267
268 fn open_write(&self, path: &Path) -> Result<Box<dyn Write + Send>, FsError> {
269 self.writes.fetch_add(1, Ordering::Relaxed);
270 self.inner.open_write(path)
271 }
272}
273
274impl<B: FsDir> FsDir for MetricsFs<B> {
275 fn read_dir(&self, path: &Path) -> Result<ReadDirIter, FsError> {
276 self.inner.read_dir(path)
277 }
278
279 fn create_dir(&self, path: &Path) -> Result<(), FsError> {
280 self.inner.create_dir(path)
281 }
282
283 fn create_dir_all(&self, path: &Path) -> Result<(), FsError> {
284 self.inner.create_dir_all(path)
285 }
286
287 fn remove_dir(&self, path: &Path) -> Result<(), FsError> {
288 self.deletes.fetch_add(1, Ordering::Relaxed);
289 self.inner.remove_dir(path)
290 }
291
292 fn remove_dir_all(&self, path: &Path) -> Result<(), FsError> {
293 self.deletes.fetch_add(1, Ordering::Relaxed);
294 self.inner.remove_dir_all(path)
295 }
296}
297
298struct ReadOnlyLayer;
304
305struct ReadOnlyFs<B> {
307 inner: B,
308}
309
310impl<B: Fs> Layer<B> for ReadOnlyLayer {
311 type Backend = ReadOnlyFs<B>;
312
313 fn layer(self, inner: B) -> Self::Backend {
314 ReadOnlyFs { inner }
315 }
316}
317
318impl<B: FsRead> FsRead for ReadOnlyFs<B> {
319 fn read(&self, path: &Path) -> Result<Vec<u8>, FsError> {
320 self.inner.read(path)
321 }
322
323 fn read_to_string(&self, path: &Path) -> Result<String, FsError> {
324 self.inner.read_to_string(path)
325 }
326
327 fn read_range(&self, path: &Path, offset: u64, len: usize) -> Result<Vec<u8>, FsError> {
328 self.inner.read_range(path, offset, len)
329 }
330
331 fn exists(&self, path: &Path) -> Result<bool, FsError> {
332 self.inner.exists(path)
333 }
334
335 fn metadata(&self, path: &Path) -> Result<Metadata, FsError> {
336 self.inner.metadata(path)
337 }
338
339 fn open_read(&self, path: &Path) -> Result<Box<dyn Read + Send>, FsError> {
340 self.inner.open_read(path)
341 }
342}
343
344impl<B: FsRead> FsWrite for ReadOnlyFs<B> {
345 fn write(&self, path: &Path, _data: &[u8]) -> Result<(), FsError> {
346 Err(FsError::PermissionDenied {
347 path: path.to_path_buf(),
348 operation: "write (read-only filesystem)",
349 })
350 }
351
352 fn append(&self, path: &Path, _data: &[u8]) -> Result<(), FsError> {
353 Err(FsError::PermissionDenied {
354 path: path.to_path_buf(),
355 operation: "append (read-only filesystem)",
356 })
357 }
358
359 fn remove_file(&self, path: &Path) -> Result<(), FsError> {
360 Err(FsError::PermissionDenied {
361 path: path.to_path_buf(),
362 operation: "remove_file (read-only filesystem)",
363 })
364 }
365
366 fn rename(&self, from: &Path, _to: &Path) -> Result<(), FsError> {
367 Err(FsError::PermissionDenied {
368 path: from.to_path_buf(),
369 operation: "rename (read-only filesystem)",
370 })
371 }
372
373 fn copy(&self, from: &Path, _to: &Path) -> Result<(), FsError> {
374 Err(FsError::PermissionDenied {
375 path: from.to_path_buf(),
376 operation: "copy (read-only filesystem)",
377 })
378 }
379
380 fn truncate(&self, path: &Path, _size: u64) -> Result<(), FsError> {
381 Err(FsError::PermissionDenied {
382 path: path.to_path_buf(),
383 operation: "truncate (read-only filesystem)",
384 })
385 }
386
387 fn open_write(&self, path: &Path) -> Result<Box<dyn Write + Send>, FsError> {
388 Err(FsError::PermissionDenied {
389 path: path.to_path_buf(),
390 operation: "open_write (read-only filesystem)",
391 })
392 }
393}
394
395impl<B: FsDir> FsDir for ReadOnlyFs<B> {
396 fn read_dir(&self, path: &Path) -> Result<ReadDirIter, FsError> {
397 self.inner.read_dir(path)
398 }
399
400 fn create_dir(&self, path: &Path) -> Result<(), FsError> {
401 Err(FsError::PermissionDenied {
402 path: path.to_path_buf(),
403 operation: "create_dir (read-only filesystem)",
404 })
405 }
406
407 fn create_dir_all(&self, path: &Path) -> Result<(), FsError> {
408 Err(FsError::PermissionDenied {
409 path: path.to_path_buf(),
410 operation: "create_dir_all (read-only filesystem)",
411 })
412 }
413
414 fn remove_dir(&self, path: &Path) -> Result<(), FsError> {
415 Err(FsError::PermissionDenied {
416 path: path.to_path_buf(),
417 operation: "remove_dir (read-only filesystem)",
418 })
419 }
420
421 fn remove_dir_all(&self, path: &Path) -> Result<(), FsError> {
422 Err(FsError::PermissionDenied {
423 path: path.to_path_buf(),
424 operation: "remove_dir_all (read-only filesystem)",
425 })
426 }
427}
428
429struct MemoryFs {
434 files: RwLock<HashMap<PathBuf, Vec<u8>>>,
435 dirs: RwLock<std::collections::HashSet<PathBuf>>,
436}
437
438impl MemoryFs {
439 fn new() -> Self {
440 let fs = Self {
441 files: RwLock::new(HashMap::new()),
442 dirs: RwLock::new(std::collections::HashSet::new()),
443 };
444 fs.dirs.write().unwrap().insert(PathBuf::from("/"));
445 fs
446 }
447}
448
449impl FsRead for MemoryFs {
450 fn read(&self, path: &Path) -> Result<Vec<u8>, FsError> {
451 self.files
452 .read()
453 .unwrap()
454 .get(path)
455 .cloned()
456 .ok_or_else(|| FsError::NotFound {
457 path: path.to_path_buf(),
458 })
459 }
460 fn read_to_string(&self, path: &Path) -> Result<String, FsError> {
461 String::from_utf8(self.read(path)?).map_err(|_| FsError::InvalidData {
462 path: path.to_path_buf(),
463 details: "not UTF-8".into(),
464 })
465 }
466 fn read_range(&self, path: &Path, offset: u64, len: usize) -> Result<Vec<u8>, FsError> {
467 let data = self.read(path)?;
468 let start = offset as usize;
469 Ok(if start >= data.len() {
470 vec![]
471 } else {
472 data[start..(start + len).min(data.len())].to_vec()
473 })
474 }
475 fn exists(&self, path: &Path) -> Result<bool, FsError> {
476 Ok(self.files.read().unwrap().contains_key(path)
477 || self.dirs.read().unwrap().contains(path))
478 }
479 fn metadata(&self, path: &Path) -> Result<Metadata, FsError> {
480 if self.dirs.read().unwrap().contains(path) {
481 Ok(Metadata {
482 file_type: FileType::Directory,
483 size: 0,
484 permissions: Permissions::default_dir(),
485 created: SystemTime::UNIX_EPOCH,
486 modified: SystemTime::UNIX_EPOCH,
487 accessed: SystemTime::UNIX_EPOCH,
488 inode: 0,
489 nlink: 1,
490 })
491 } else if let Some(data) = self.files.read().unwrap().get(path) {
492 Ok(Metadata {
493 file_type: FileType::File,
494 size: data.len() as u64,
495 permissions: Permissions::default_file(),
496 created: SystemTime::UNIX_EPOCH,
497 modified: SystemTime::UNIX_EPOCH,
498 accessed: SystemTime::UNIX_EPOCH,
499 inode: 0,
500 nlink: 1,
501 })
502 } else {
503 Err(FsError::NotFound {
504 path: path.to_path_buf(),
505 })
506 }
507 }
508 fn open_read(&self, path: &Path) -> Result<Box<dyn Read + Send>, FsError> {
509 Ok(Box::new(std::io::Cursor::new(self.read(path)?)))
510 }
511}
512
513impl FsWrite for MemoryFs {
514 fn write(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
515 self.files
516 .write()
517 .unwrap()
518 .insert(path.to_path_buf(), data.to_vec());
519 Ok(())
520 }
521 fn append(&self, path: &Path, data: &[u8]) -> Result<(), FsError> {
522 self.files
523 .write()
524 .unwrap()
525 .entry(path.to_path_buf())
526 .or_default()
527 .extend_from_slice(data);
528 Ok(())
529 }
530 fn remove_file(&self, path: &Path) -> Result<(), FsError> {
531 self.files
532 .write()
533 .unwrap()
534 .remove(path)
535 .map(|_| ())
536 .ok_or_else(|| FsError::NotFound {
537 path: path.to_path_buf(),
538 })
539 }
540 fn rename(&self, from: &Path, to: &Path) -> Result<(), FsError> {
541 let data = self
542 .files
543 .write()
544 .unwrap()
545 .remove(from)
546 .ok_or_else(|| FsError::NotFound {
547 path: from.to_path_buf(),
548 })?;
549 self.files.write().unwrap().insert(to.to_path_buf(), data);
550 Ok(())
551 }
552 fn copy(&self, from: &Path, to: &Path) -> Result<(), FsError> {
553 let data = self.read(from)?;
554 self.write(to, &data)
555 }
556 fn truncate(&self, path: &Path, size: u64) -> Result<(), FsError> {
557 self.files
558 .write()
559 .unwrap()
560 .get_mut(path)
561 .ok_or_else(|| FsError::NotFound {
562 path: path.to_path_buf(),
563 })?
564 .resize(size as usize, 0);
565 Ok(())
566 }
567 fn open_write(&self, _path: &Path) -> Result<Box<dyn Write + Send>, FsError> {
568 Ok(Box::new(std::io::Cursor::new(Vec::new())))
569 }
570}
571
572impl FsDir for MemoryFs {
573 fn read_dir(&self, path: &Path) -> Result<ReadDirIter, FsError> {
574 if !self.dirs.read().unwrap().contains(path) {
575 return Err(FsError::NotFound {
576 path: path.to_path_buf(),
577 });
578 }
579 let mut entries = Vec::new();
580 for (fp, data) in self.files.read().unwrap().iter() {
581 if fp.parent() == Some(path) {
582 if let Some(name) = fp.file_name() {
583 entries.push(Ok(DirEntry {
584 name: name.to_string_lossy().into(),
585 path: fp.clone(),
586 file_type: FileType::File,
587 size: data.len() as u64,
588 inode: 0,
589 }));
590 }
591 }
592 }
593 for dp in self.dirs.read().unwrap().iter() {
594 if dp.parent() == Some(path) && dp != path {
595 if let Some(name) = dp.file_name() {
596 entries.push(Ok(DirEntry {
597 name: name.to_string_lossy().into(),
598 path: dp.clone(),
599 file_type: FileType::Directory,
600 size: 0,
601 inode: 0,
602 }));
603 }
604 }
605 }
606 Ok(ReadDirIter::from_vec(entries))
607 }
608 fn create_dir(&self, path: &Path) -> Result<(), FsError> {
609 if self.dirs.read().unwrap().contains(path) {
610 return Err(FsError::AlreadyExists {
611 path: path.to_path_buf(),
612 operation: "create_dir",
613 });
614 }
615 self.dirs.write().unwrap().insert(path.to_path_buf());
616 Ok(())
617 }
618 fn create_dir_all(&self, path: &Path) -> Result<(), FsError> {
619 let mut current = PathBuf::new();
620 for c in path.components() {
621 current.push(c);
622 self.dirs.write().unwrap().insert(current.clone());
623 }
624 Ok(())
625 }
626 fn remove_dir(&self, path: &Path) -> Result<(), FsError> {
627 if !self.dirs.write().unwrap().remove(path) {
628 return Err(FsError::NotFound {
629 path: path.to_path_buf(),
630 });
631 }
632 Ok(())
633 }
634 fn remove_dir_all(&self, path: &Path) -> Result<(), FsError> {
635 self.dirs.write().unwrap().remove(path);
636 self.files
637 .write()
638 .unwrap()
639 .retain(|p, _| !p.starts_with(path));
640 Ok(())
641 }
642}
643
644fn main() {
649 println!("=== Layer Middleware Example ===\n");
650
651 let base = MemoryFs::new();
653
654 base.write(Path::new("/config.txt"), b"initial config")
656 .unwrap();
657 base.create_dir(Path::new("/data")).unwrap();
658 base.write(Path::new("/data/file1.txt"), b"file 1 content")
659 .unwrap();
660
661 println!("--- Example 1: Logging Layer ---\n");
665
666 let logged_fs = base.layer(LoggingLayer);
668
669 println!("Reading a file through logging layer:");
670 let _ = logged_fs.read(Path::new("/config.txt"));
671 println!();
672
673 let base = MemoryFs::new();
675 base.write(Path::new("/config.txt"), b"initial config")
676 .unwrap();
677 base.create_dir(Path::new("/data")).unwrap();
678 base.write(Path::new("/data/file1.txt"), b"file 1 content")
679 .unwrap();
680 base.write(Path::new("/data/file2.txt"), b"file 2 content")
681 .unwrap();
682
683 println!("--- Example 2: Metrics Layer ---\n");
687
688 let metrics_layer = MetricsLayer;
689 let metrics_fs = metrics_layer.layer(MemoryFs::new());
690
691 metrics_fs.write(Path::new("/a.txt"), b"a").unwrap();
693 metrics_fs.write(Path::new("/b.txt"), b"b").unwrap();
694 metrics_fs.write(Path::new("/c.txt"), b"c").unwrap();
695 let _ = metrics_fs.read(Path::new("/a.txt"));
696 let _ = metrics_fs.read(Path::new("/b.txt"));
697 metrics_fs.remove_file(Path::new("/c.txt")).unwrap();
698
699 let (reads, writes, deletes) = metrics_fs.stats();
700 println!("Metrics: reads={reads}, writes={writes}, deletes={deletes}\n");
701
702 println!("--- Example 3: Read-Only Layer ---\n");
706
707 let readonly_fs = base.layer(ReadOnlyLayer);
708
709 println!("Reading through read-only layer:");
711 match readonly_fs.read(Path::new("/config.txt")) {
712 Ok(data) => println!(" Success: {} bytes", data.len()),
713 Err(e) => println!(" Error: {e}"),
714 }
715
716 println!("Writing through read-only layer:");
718 match readonly_fs.write(Path::new("/new.txt"), b"test") {
719 Ok(()) => println!(" Success (unexpected!)"),
720 Err(e) => println!(" Error: {e}"),
721 }
722 println!();
723
724 println!("--- Example 4: Composing Layers ---\n");
728
729 let base = MemoryFs::new();
732 let with_metrics = MetricsLayer.layer(base);
733 let with_logging = LoggingLayer.layer(with_metrics);
734
735 println!("Writing through Logging -> Metrics -> Memory:");
736 with_logging
737 .write(Path::new("/test.txt"), b"hello")
738 .unwrap();
739 println!();
740
741 println!("Reading through Logging -> Metrics -> Memory:");
742 let _ = with_logging.read(Path::new("/test.txt"));
743 println!();
744
745 let (reads, writes, _) = with_logging.inner.stats();
747 println!("Inner metrics: reads={reads}, writes={writes}\n");
748
749 println!("--- Example 5: Layers with Trait Objects ---\n");
753
754 fn use_any_fs(fs: &dyn Fs) {
755 let _ = fs.exists(Path::new("/"));
756 println!(" Used filesystem through trait object");
757 }
758
759 let base = MemoryFs::new();
760 let layered = base.layer(LoggingLayer);
761
762 println!("Passing layered FS as &dyn Fs:");
763 use_any_fs(&layered);
764
765 println!("\n=== Layer examples complete! ===");
766}