mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-23 06:05:24 +00:00
VFS crate
This commit is contained in:
116
vfs/src/lib.rs
Normal file
116
vfs/src/lib.rs
Normal 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
36
vfs/src/noop_backend.rs
Normal 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
37
vfs/src/std_backend.rs
Normal 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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user