use std::io::{Read, Seek, Write};
use std::path::Path;
pub trait FileSystem: Send + Sync {
fn can_handle(&self, path: &str) -> bool;
fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>>;
fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>>;
fn exists(&self, path: &str) -> bool;
fn remove(&self, path: &str) -> std::io::Result<()>;
fn create_dir_all(&self, path: &str) -> std::io::Result<()>;
}
pub trait FileRead: Read + Seek + Send {}
pub trait FileWrite: Write + Seek + Send {}
#[derive(Default)]
pub struct LocalFileSystem;
impl FileSystem for LocalFileSystem {
fn can_handle(&self, _path: &str) -> bool {
true
}
fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>> {
Ok(Box::new(std::fs::File::open(Path::new(path))?))
}
fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>> {
Ok(Box::new(std::fs::File::create(Path::new(path))?))
}
fn exists(&self, path: &str) -> bool {
Path::new(path).exists()
}
fn remove(&self, path: &str) -> std::io::Result<()> {
std::fs::remove_file(Path::new(path))
}
fn create_dir_all(&self, path: &str) -> std::io::Result<()> {
std::fs::create_dir_all(Path::new(path))
}
}
impl FileRead for std::fs::File {}
impl FileWrite for std::fs::File {}
use std::sync::RwLock;
pub struct VirtualFileSystemRegistry {
systems: RwLock<Vec<Box<dyn FileSystem>>>,
default_fs: LocalFileSystem,
}
impl Default for VirtualFileSystemRegistry {
fn default() -> Self {
Self::new()
}
}
impl VirtualFileSystemRegistry {
pub fn new() -> Self {
Self {
systems: RwLock::new(Vec::new()),
default_fs: LocalFileSystem,
}
}
pub fn register_file_system(&self, fs: Box<dyn FileSystem>) {
let mut systems = self.systems.write().unwrap();
systems.push(fs);
}
pub fn open_read(&self, path: &str) -> std::io::Result<Box<dyn FileRead>> {
let systems = self.systems.read().unwrap();
for fs in systems.iter() {
if fs.can_handle(path) {
return fs.open_read(path);
}
}
self.default_fs.open_read(path)
}
pub fn open_write(&self, path: &str) -> std::io::Result<Box<dyn FileWrite>> {
let systems = self.systems.read().unwrap();
for fs in systems.iter() {
if fs.can_handle(path) {
return fs.open_write(path);
}
}
self.default_fs.open_write(path)
}
pub fn exists(&self, path: &str) -> bool {
let systems = self.systems.read().unwrap();
for fs in systems.iter() {
if fs.can_handle(path) {
return fs.exists(path);
}
}
self.default_fs.exists(path)
}
pub fn remove(&self, path: &str) -> std::io::Result<()> {
let systems = self.systems.read().unwrap();
for fs in systems.iter() {
if fs.can_handle(path) {
return fs.remove(path);
}
}
self.default_fs.remove(path)
}
pub fn create_dir_all(&self, path: &str) -> std::io::Result<()> {
let systems = self.systems.read().unwrap();
for fs in systems.iter() {
if fs.can_handle(path) {
return fs.create_dir_all(path);
}
}
self.default_fs.create_dir_all(path)
}
}