akar_common/
file_system.rs1use std::io::{Read, Seek, Write};
7use std::path::Path;
8
9pub trait FileSystem: Send + Sync {
11 fn can_handle(&self, path: &str) -> bool;
13
14 fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>>;
16
17 fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>>;
19
20 fn exists(&self, path: &str) -> bool;
22
23 fn remove(&self, path: &str) -> std::io::Result<()>;
25
26 fn create_dir_all(&self, path: &str) -> std::io::Result<()>;
28}
29
30pub trait FileRead: Read + Seek + Send {}
32
33pub trait FileWrite: Write + Seek + Send {}
35
36#[derive(Default)]
38pub struct LocalFileSystem;
39
40impl FileSystem for LocalFileSystem {
41 fn can_handle(&self, _path: &str) -> bool {
42 true
44 }
45
46 fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>> {
47 Ok(Box::new(std::fs::File::open(Path::new(path))?))
48 }
49
50 fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>> {
51 Ok(Box::new(std::fs::File::create(Path::new(path))?))
52 }
53
54 fn exists(&self, path: &str) -> bool {
55 Path::new(path).exists()
56 }
57
58 fn remove(&self, path: &str) -> std::io::Result<()> {
59 std::fs::remove_file(Path::new(path))
60 }
61
62 fn create_dir_all(&self, path: &str) -> std::io::Result<()> {
63 std::fs::create_dir_all(Path::new(path))
64 }
65}
66
67impl FileRead for std::fs::File {}
68impl FileWrite for std::fs::File {}
69
70use std::sync::RwLock;
71
72pub struct VirtualFileSystemRegistry {
74 systems: RwLock<Vec<Box<dyn FileSystem>>>,
75 default_fs: LocalFileSystem,
76}
77
78impl Default for VirtualFileSystemRegistry {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84impl VirtualFileSystemRegistry {
85 pub fn new() -> Self {
86 Self {
87 systems: RwLock::new(Vec::new()),
88 default_fs: LocalFileSystem,
89 }
90 }
91
92 pub fn register_file_system(&self, fs: Box<dyn FileSystem>) {
93 let mut systems = self.systems.write().unwrap();
94 systems.push(fs);
95 }
96
97 pub fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>> {
98 let systems = self.systems.read().unwrap();
99 for fs in systems.iter() {
100 if fs.can_handle(path) {
101 return fs.open_read(path);
102 }
103 }
104 self.default_fs.open_read(path)
105 }
106
107 pub fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>> {
108 let systems = self.systems.read().unwrap();
109 for fs in systems.iter() {
110 if fs.can_handle(path) {
111 return fs.open_write(path);
112 }
113 }
114 self.default_fs.open_write(path)
115 }
116
117 pub fn exists(&self, path: &str) -> bool {
118 let systems = self.systems.read().unwrap();
119 for fs in systems.iter() {
120 if fs.can_handle(path) {
121 return fs.exists(path);
122 }
123 }
124 self.default_fs.exists(path)
125 }
126
127 pub fn remove(&self, path: &str) -> std::io::Result<()> {
128 let systems = self.systems.read().unwrap();
129 for fs in systems.iter() {
130 if fs.can_handle(path) {
131 return fs.remove(path);
132 }
133 }
134 self.default_fs.remove(path)
135 }
136
137 pub fn create_dir_all(&self, path: &str) -> std::io::Result<()> {
138 let systems = self.systems.read().unwrap();
139 for fs in systems.iter() {
140 if fs.can_handle(path) {
141 return fs.create_dir_all(path);
142 }
143 }
144 self.default_fs.create_dir_all(path)
145 }
146}