pub struct DirFS { /* private fields */ }Expand description
A virtual filesystem (VFS) implementation that maps to a real directory on the host system.
DirFS provides an isolated, path‑normalized view of a portion of the filesystem, rooted at a
designated absolute path (root). It maintains an internal state of valid paths and supports
standard operations:
- Navigate via
cd()(change working directory). - Create directories (
mkdir()) and files (mkfile()). - Remove entries (
rm()). - Check existence (
exists()). - Read and write content (
read()/write()/append()).
§Usage notes:
DirFSdoes not follow symlinks;rm()removes the link, not the target.- Permissions are not automatically adjusted; ensure
rootis writable. - Not thread‑safe in current version (wrap in
Mutexif needed). - Errors are returned via
anyhow::Resultwith descriptive messages.
§Example:
use vfs_kit::{DirFS, FsBackend};
let tmp = std::env::temp_dir();
let root = tmp.join("my_vfs");
let mut fs = DirFS::new(root).unwrap();
fs.mkdir("/docs").unwrap();
fs.mkfile("/docs/note.txt", Some(b"Hello")).unwrap();
assert!(fs.exists("/docs/note.txt"));
fs.rm("/docs/note.txt").unwrap();Implementations§
Source§impl DirFS
impl DirFS
Sourcepub fn new<P: AsRef<Path>>(root: P) -> Result<Self>
pub fn new<P: AsRef<Path>>(root: P) -> Result<Self>
Creates a new DirFs instance with the root directory at path.
Checks permissions to create and write into path.
pathis an absolute host path. Ifpathis not absolute, error returns.
Sourcepub fn set_auto_clean(&mut self, clean: bool)
pub fn set_auto_clean(&mut self, clean: bool)
Changes auto-clean flag. If auto-clean flag is true all created in vfs artifacts will be removed on drop.
Sourcepub fn add<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
pub fn add<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
Adds an existing artifact (file or directory) to the VFS. The artifact must exist and be located in the VFS root directory. If artifact is directory - all its childs will be added recursively. Once added, it will be managed by the VFS (e.g., deleted upon destruction).
pathis an inner VFS path.
Sourcepub fn forget<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
pub fn forget<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
Removes a file or directory from the VFS and recursively untracks all its contents.
This method “forgets” the specified path — it is permanently removed from the VFS tracking. If the path is a directory, all its children (files and subdirectories) are also untracked recursively.
§Arguments
path- The path to remove from the VFS. Can be a file or a directory.
§Returns
Ok(())- If the path was successfully removed (or was not tracked in the first place).Err(anyhow::Error)- If:- The path is not tracked by the VFS.
- The path is the root directory (
/), which cannot be forgotten.
§Behavior
- Existence check: Returns an error if the resolved path is not currently tracked.
- Root protection: Blocks attempts to forget the root directory (
/). - Removal:
- If the path is a file: removes only that file.
- If the path is a directory: removes the directory and all its descendants (recursively).
§Examples
use vfs_kit::{DirFS, FsBackend};
let temp_dir = tempdir::TempDir::new("vfs_example").unwrap();
let mut vfs = DirFS::new(temp_dir.path()).unwrap();
vfs.mkdir("/docs/backup");
vfs.mkfile("/docs/readme.txt", None);
// Forget the entire /docs directory (and all its contents)
vfs.forget("/docs").unwrap();
assert!(!vfs.exists("/docs/readme.txt"));
assert!(!vfs.exists("/docs/backup"));use vfs_kit::{DirFS, FsBackend};
let temp_dir = tempdir::TempDir::new("vfs_example").unwrap();
let mut vfs = DirFS::new(temp_dir.path()).unwrap();
// Error: trying to forget a non-existent path
assert!(vfs.forget("/nonexistent").is_err());
// Error: trying to forget the root
assert!(vfs.forget("/").is_err());§Notes
- The method does not interact with the real filesystem — it only affects the VFS’s internal tracking.
- If the path does not exist in the VFS, the method returns an error
(unlike
removein some systems that may silently succeed).
Trait Implementations§
Source§impl FsBackend for DirFS
impl FsBackend for DirFS
Source§fn cd<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
fn cd<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
Changes the current working directory.
pathcan be in relative or absolute form, but in both cases it must exist. An error is returned if the specifiedpathdoes not exist.
Source§fn exists<P: AsRef<Path>>(&self, path: P) -> bool
fn exists<P: AsRef<Path>>(&self, path: P) -> bool
Checks if a path exists in the vfs.
The path can be:
- absolute (starting with ‘/’),
- relative (relative to the vfs cwd),
- contain ‘..’ or ‘.’.
Source§fn ls<P: AsRef<Path>>(
&self,
path: Option<P>,
) -> Result<impl Iterator<Item = DirEntry>>
fn ls<P: AsRef<Path>>( &self, path: Option<P>, ) -> Result<impl Iterator<Item = DirEntry>>
Returns an iterator over directory entries at a specific depth (shallow listing).
This method lists only the immediate children of the given directory (or CWD if None),
i.e., entries that are exactly one level below the specified path.
It does not recurse into subdirectories (see tree() if you need recurse).
§Arguments
path- Optional path to the directory to list:Some(p): list contents of directoryp(must exist in VFS).None: list contents of the current working directory (cwd).
§Returns
Ok(impl Iterator<Item = DirEntry>)- Iterator over entries of immediate children (relative to VFS root). The yielded paths are inside the target directory but do not include deeper nesting.Err(anyhow::Error)- If the specified path does not exist in VFS.
§Example:
use std::path::Path;
use vfs_kit::{DirEntry, DirFS, FsBackend};
let temp_dir = tempdir::TempDir::new("vfs_example").unwrap();
let mut fs = DirFS::new(temp_dir.path()).unwrap();
fs.mkdir("/docs/subdir");
fs.mkfile("/docs/document.txt", None);
// List current directory contents
for entry in fs.ls::<&Path>(None).unwrap() {
println!("{:?}", entry);
}
// List contents of "/docs"
for entry in fs.ls(Some("/docs")).unwrap() {
if entry.is_file() {
println!("File: {:?}", entry);
} else {
println!("Dir: {:?}", entry);
}
}§Notes
- No recursion: Unlike
tree(), this method does not traverse subdirectories. - Path ownership: The returned iterator borrows from the VFS’s internal state.
It is valid as long as
selflives. - Excludes root: The input directory itself is not included in the output.
- Error handling: If
pathdoes not exist, an error is returned before iteration. - Performance: The filtering is done in‑memory; no additional filesystem I/O occurs during iteration.
Source§fn tree<P: AsRef<Path>>(
&self,
path: Option<P>,
) -> Result<impl Iterator<Item = DirEntry>>
fn tree<P: AsRef<Path>>( &self, path: Option<P>, ) -> Result<impl Iterator<Item = DirEntry>>
Returns a recursive iterator over the directory tree starting from a given path.
The iterator yields all entries (files and directories) that are inside the specified directory (i.e., the starting directory itself is not included).
§Arguments
path- Optional path to the directory to traverse:Some(p): start from directoryp(must exist in VFS).None: start from the current working directory (cwd).
§Returns
Ok(impl Iterator<Item = DirEntry>)- Iterator over all entries within the tree (relative to VFS root), excluding the root of the traversal.Err(anyhow::Error)- If:- The specified path does not exist in VFS.
- The path is not a directory (implicitly checked via
existsand tree structure).
§Behavior
- Recursive traversal: Includes all nested files and directories.
- Excludes root: The starting directory path is not yielded (only its contents).
- Path normalization: Input path is normalized.
- VFS-only: Only returns paths tracked in VFS.
- Performance: The filtering is done in‑memory; no additional filesystem I/O occurs during iteration.
§Example:
use std::path::Path;
use vfs_kit::{DirFS, FsBackend};
let temp_dir = tempdir::TempDir::new("vfs_example").unwrap();
let mut fs = DirFS::new(temp_dir.path()).unwrap();
fs.mkdir("/docs/subdir");
fs.mkfile("/docs/document.txt", None);
// Iterate over current working directory
for entry in fs.tree::<&Path>(None).unwrap() {
println!("{:?}", entry);
}
// Iterate over a specific directory
for entry in fs.tree(Some("/docs")).unwrap() {
if entry.is_file() {
println!("File: {:?}", entry);
}
}§Notes
- The iterator borrows data from VFS. The returned iterator is valid as long
as
selfis alive. - Symbolic links are treated as regular entries (no follow/resolve).
- Use
Pathmethods (e.g.,is_file(),is_dir()) on yielded items for type checks.
Source§fn mkdir<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
fn mkdir<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
Creates directory and all it parents (if needed).
path- inner vfs path.
Source§fn mkfile<P: AsRef<Path>>(
&mut self,
file_path: P,
content: Option<&[u8]>,
) -> Result<()>
fn mkfile<P: AsRef<Path>>( &mut self, file_path: P, content: Option<&[u8]>, ) -> Result<()>
Creates new file in vfs.
file_pathmust be inner vfs path. It must contain the name of the file, optionally preceded by existing parent directory. If the parent directory does not exist, an error is returned.
Source§fn read<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>>
fn read<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>>
Reads the entire contents of a file into a byte vector.
pathis the inner VFS path.
§Returns
Ok(Vec<u8>)- File content as a byte vector if successful.Err(anyhow::Error)- If any of the following occurs:- File does not exist in VFS (
file does not exist: ...) - Path points to a directory (
... is a directory) - Permission issues when accessing the host file
- I/O errors during reading
- File does not exist in VFS (
§Notes
- Does not follow symbolic links on the host filesystem (reads the link itself).
- Returns an empty vector for empty files.
Source§fn write<P: AsRef<Path>>(&self, path: P, content: &[u8]) -> Result<()>
fn write<P: AsRef<Path>>(&self, path: P, content: &[u8]) -> Result<()>
Writes bytes to an existing file, replacing its entire contents.
path- Path to the file.content- Byte slice (&[u8]) to write to the file.
§Returns
Ok(())- If the write operation succeeded.Err(anyhow::Error)- If any of the following occurs:- File does not exist in VFS (
file does not exist: ...) - Path points to a directory (
... is a directory) - Permission issues when accessing the host file
- I/O errors during writing (e.g., disk full, invalid path)
- File does not exist in VFS (
§Behavior
- Overwrites completely: The entire existing content is replaced.
- No file creation: File must exist (use
mkfile()first). - Atomic operation: Uses
std::fs::write()which replaces the file in one step. - Permissions: The file retains its original permissions (no chmod is performed).
Source§fn append<P: AsRef<Path>>(&self, path: P, content: &[u8]) -> Result<()>
fn append<P: AsRef<Path>>(&self, path: P, content: &[u8]) -> Result<()>
Appends bytes to the end of an existing file, preserving its old contents.
§Arguments
path- Path to the existing file.content- Byte slice (&[u8]) to append to the file.
§Returns
Ok(())- If the append operation succeeded.Err(anyhow::Error)- If any of the following occurs:- File does not exist in VFS (
file does not exist: ...) - Path points to a directory (
... is a directory) - Permission issues when accessing the host file
- I/O errors during writing (e.g., disk full, invalid path)
- File does not exist in VFS (
§Behavior
- Appends only: Existing content is preserved; new bytes are added at the end.
- No parent creation: Parent directories must exist (use
mkdir()first if needed). - File creation: Does NOT create the file if it doesn’t exist (returns error).
- Permissions: The file retains its original permissions.
Source§fn rm<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
fn rm<P: AsRef<Path>>(&mut self, path: P) -> Result<()>
Removes a file or directory at the specified path.
path: can be absolute (starting with ‘/’) or relative to the current working directory (cwd).- If the path is a directory, all its contents are removed recursively.
Returns:
Ok(())on successful removal.Err(_)if:- the path does not exist in the VFS;
- there are insufficient permissions;
- a filesystem error occurs.