VFS crate

This commit is contained in:
Lucien Greathouse
2020-02-18 22:30:12 -08:00
parent 8f21514855
commit 838e8f6bde
6 changed files with 214 additions and 7 deletions

116
vfs/src/lib.rs Normal file
View File

@@ -0,0 +1,116 @@
mod noop_backend;
mod std_backend;
use std::io;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
pub use noop_backend::NoopBackend;
pub use std_backend::StdBackend;
pub trait VfsBackend {
fn read(&self, path: &Path) -> io::Result<Vec<u8>>;
fn write(&self, path: &Path, data: &[u8]) -> io::Result<()>;
fn read_dir(&self, path: &Path) -> io::Result<ReadDir>;
fn metadata(&self, path: &Path) -> io::Result<Metadata>;
}
pub struct DirEntry {
path: PathBuf,
}
impl DirEntry {
pub fn path(&self) -> &Path {
&self.path
}
}
pub struct ReadDir {
inner: Box<dyn Iterator<Item = io::Result<DirEntry>>>,
}
impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
pub struct Metadata {
is_file: bool,
}
impl Metadata {
pub fn is_file(&self) -> bool {
self.is_file
}
pub fn is_dir(&self) -> bool {
!self.is_file
}
}
struct VfsLock {
data: (),
backend: Box<dyn VfsBackend>,
}
impl VfsLock {
pub fn read<P: AsRef<Path>>(&mut self, path: P) -> io::Result<Arc<Vec<u8>>> {
let path = path.as_ref();
let contents = self.backend.read(path)?;
Ok(Arc::new(contents))
}
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(
&mut self,
path: P,
contents: C,
) -> io::Result<()> {
let path = path.as_ref();
let contents = contents.as_ref();
self.backend.write(path, contents)
}
pub fn read_dir<P: AsRef<Path>>(&mut self, path: P) -> io::Result<ReadDir> {
let path = path.as_ref();
self.backend.read_dir(path)
}
}
pub struct Vfs {
inner: Mutex<VfsLock>,
}
impl Vfs {
pub fn new<B: VfsBackend + 'static>(backend: B) -> Self {
let lock = VfsLock {
data: (),
backend: Box::new(backend),
};
Self {
inner: Mutex::new(lock),
}
}
pub fn read<P: AsRef<Path>>(&self, path: P) -> io::Result<Arc<Vec<u8>>> {
let path = path.as_ref();
let mut inner = self.inner.lock().unwrap();
inner.read(path)
}
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> {
let path = path.as_ref();
let contents = contents.as_ref();
let mut inner = self.inner.lock().unwrap();
inner.write(path, contents)
}
pub fn read_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<ReadDir> {
let path = path.as_ref();
let mut inner = self.inner.lock().unwrap();
inner.read_dir(path)
}
}

36
vfs/src/noop_backend.rs Normal file
View File

@@ -0,0 +1,36 @@
use std::io;
use std::path::Path;
use crate::{Metadata, ReadDir, VfsBackend};
pub struct NoopBackend;
impl VfsBackend for NoopBackend {
fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
Err(io::Error::new(
io::ErrorKind::Other,
"NoopBackend doesn't do anything",
))
}
fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> {
Err(io::Error::new(
io::ErrorKind::Other,
"NoopBackend doesn't do anything",
))
}
fn read_dir(&self, path: &Path) -> io::Result<ReadDir> {
Err(io::Error::new(
io::ErrorKind::Other,
"NoopBackend doesn't do anything",
))
}
fn metadata(&self, path: &Path) -> io::Result<Metadata> {
Err(io::Error::new(
io::ErrorKind::Other,
"NoopBackend doesn't do anything",
))
}
}

37
vfs/src/std_backend.rs Normal file
View File

@@ -0,0 +1,37 @@
use std::fs;
use std::io;
use std::path::Path;
use crate::{DirEntry, Metadata, ReadDir, VfsBackend};
pub struct StdBackend;
impl VfsBackend for StdBackend {
fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
fs::read(path)
}
fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> {
fs::write(path, data)
}
fn read_dir(&self, path: &Path) -> io::Result<ReadDir> {
let inner = fs::read_dir(path)?.map(|entry| {
Ok(DirEntry {
path: entry?.path(),
})
});
Ok(ReadDir {
inner: Box::new(inner),
})
}
fn metadata(&self, path: &Path) -> io::Result<Metadata> {
let inner = fs::metadata(path)?;
Ok(Metadata {
is_file: inner.is_file(),
})
}
}