mod memory;
mod mountable;
#[cfg(feature = "native-fs")]
mod overlay;
#[cfg(feature = "native-fs")]
mod readwrite;
#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "native-fs"))]
mod readwrite_tests;
#[cfg(all(test, feature = "native-fs"))]
mod overlay_tests;
#[cfg(test)]
mod mountable_tests;
pub use memory::InMemoryFs;
pub use mountable::MountableFs;
#[cfg(feature = "native-fs")]
pub use overlay::OverlayFs;
#[cfg(feature = "native-fs")]
pub use readwrite::ReadWriteFs;
use crate::error::VfsError;
use crate::platform::SystemTime;
use std::path::{Path, PathBuf};
use std::sync::Arc;
pub(crate) fn vfs_path_is_absolute(path: &Path) -> bool {
path.to_str().is_some_and(|s| s.starts_with('/'))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Metadata {
pub node_type: NodeType,
pub size: u64,
pub mode: u32,
pub mtime: SystemTime,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeType {
File,
Directory,
Symlink,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DirEntry {
pub name: String,
pub node_type: NodeType,
}
#[derive(Debug, Clone)]
pub enum FsNode {
File {
content: Vec<u8>,
mode: u32,
mtime: SystemTime,
},
Directory {
children: std::collections::BTreeMap<String, FsNode>,
mode: u32,
mtime: SystemTime,
},
Symlink {
target: PathBuf,
mtime: SystemTime,
},
}
#[derive(Debug, Clone, Default)]
pub struct GlobOptions {
pub dotglob: bool,
pub nocaseglob: bool,
pub globstar: bool,
pub extglob: bool,
}
pub trait VirtualFs: Send + Sync {
fn read_file(&self, path: &Path) -> Result<Vec<u8>, VfsError>;
fn write_file(&self, path: &Path, content: &[u8]) -> Result<(), VfsError>;
fn append_file(&self, path: &Path, content: &[u8]) -> Result<(), VfsError>;
fn remove_file(&self, path: &Path) -> Result<(), VfsError>;
fn mkdir(&self, path: &Path) -> Result<(), VfsError>;
fn mkdir_p(&self, path: &Path) -> Result<(), VfsError>;
fn readdir(&self, path: &Path) -> Result<Vec<DirEntry>, VfsError>;
fn remove_dir(&self, path: &Path) -> Result<(), VfsError>;
fn remove_dir_all(&self, path: &Path) -> Result<(), VfsError>;
fn exists(&self, path: &Path) -> bool;
fn stat(&self, path: &Path) -> Result<Metadata, VfsError>;
fn lstat(&self, path: &Path) -> Result<Metadata, VfsError>;
fn chmod(&self, path: &Path, mode: u32) -> Result<(), VfsError>;
fn utimes(&self, path: &Path, mtime: SystemTime) -> Result<(), VfsError>;
fn symlink(&self, target: &Path, link: &Path) -> Result<(), VfsError>;
fn hardlink(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
fn readlink(&self, path: &Path) -> Result<PathBuf, VfsError>;
fn canonicalize(&self, path: &Path) -> Result<PathBuf, VfsError>;
fn copy(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
fn rename(&self, src: &Path, dst: &Path) -> Result<(), VfsError>;
fn glob(&self, pattern: &str, cwd: &Path) -> Result<Vec<PathBuf>, VfsError>;
fn glob_with_opts(
&self,
pattern: &str,
cwd: &Path,
_opts: &GlobOptions,
) -> Result<Vec<PathBuf>, VfsError> {
self.glob(pattern, cwd)
}
fn deep_clone(&self) -> Arc<dyn VirtualFs>;
}