Skip to main content

DirFS

Struct DirFS 

Source
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 all operations defined in FsBackend trait.

§Usage notes:

  • DirFS does not follow symlinks; rm() removes the link, not the target.
  • Permissions are not automatically adjusted; ensure root is writable.
  • Not thread‑safe in current version (wrap in Mutex if needed).
  • Errors are returned via anyhow::Result with 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

Source

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.

  • path is an absolute host path. If path not exists it will be created. If path is not absolute or path is not a directory, error returns. By default, the is_auto_clean flag is set to true.
Source

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.

Source

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).

  • path is an inner VFS path.
Source

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 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
  1. Existence check: Returns an error if the resolved path is not currently tracked.
  2. Root protection: Blocks attempts to forget the root directory (/).
  3. 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
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"));
// 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 remove in some systems that may silently succeed).

Trait Implementations§

Source§

impl Drop for DirFS

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl FsBackend for DirFS

Source§

fn root(&self) -> &Path

Returns root path related to the host file system.

Source§

fn cwd(&self) -> &Path

Returns current working directory related to the vfs root.

Source§

fn to_host<P: AsRef<Path>>(&self, inner_path: P) -> Result<PathBuf>

Returns the path on the host system that matches the specified internal path.

  • inner_path must exist in VFS
Source§

fn cd<P: AsRef<Path>>(&mut self, path: P) -> Result<()>

Changes the current working directory.

  • path can be in relative or absolute form, but in both cases it must exist in VFS. An error is returned if the specified path does not exist.
Source§

fn exists<P: AsRef<Path>>(&self, path: P) -> bool

Checks if a path exists in the VFS. The path can be in relative or absolute form.

Source§

fn is_dir<P: AsRef<Path>>(&self, path: P) -> Result<bool>

Checks if path is a directory.

Source§

fn is_file<P: AsRef<Path>>(&self, path: P) -> Result<bool>

Checks if path is a regular file.

Source§

fn ls<P: AsRef<Path>>(&self, path: P) -> Result<impl Iterator<Item = &Path>>

Returns an iterator over directory entries at a specific depth (shallow listing).

This method lists only the immediate children of the given directory, 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 - path to the directory to list (must exist in VFS).
§Returns
  • Ok(impl Iterator<Item = &Path>) - 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:
 fs.mkdir("/docs/subdir");
 fs.mkfile("/docs/document.txt", None);

 // List root contents
 for entry in fs.ls("/").unwrap() {
     println!("{:?}", entry);
 }

 // List contents of "/docs"
 for entry in fs.ls("/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 self lives.
  • Excludes root: The input directory itself is not included in the output.
  • Error handling: If path does 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: P) -> Result<impl Iterator<Item = &Path>>

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 - path to the directory to traverse (must exist in VFS).
§Returns
  • Ok(impl Iterator<Item = &Path>) - 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 exists and 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:
fs.mkdir("/docs/subdir");
fs.mkfile("/docs/document.txt", None);

// Iterate over current working directory
for entry in fs.tree("/").unwrap() {
    println!("{:?}", entry);
}

// Iterate over a specific directory
for entry in fs.tree("/docs").unwrap() {
    if entry.is_file() {
        println!("File: {:?}", entry);
    }
}
§Notes
  • The iterator borrows data from VFS. The returned iterator is valid as long as self is alive.
  • Symbolic links are treated as regular entries (no follow/resolve).
  • Use DirFS methods (e.g., is_file(), is_dir()) for yielded items for type checks.
Source§

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<()>

Creates new file in VFS.

  • file_path must be inner VFS path. It must contain the name of the file, optionally preceded by parent directory. If the parent directory does not exist, it will be created.
Source§

fn read<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>>

Reads the entire contents of a file into a byte vector.

  • path is 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
§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>>(&mut 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)
§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>>(&mut 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)
§Behavior
  • Appends only: Existing content is preserved; new bytes are added at the end.
  • 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<()>

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.
Source§

fn cleanup(&mut self) -> bool

Removes all artifacts (dirs and files) in vfs, but preserve its root.

Auto Trait Implementations§

§

impl Freeze for DirFS

§

impl RefUnwindSafe for DirFS

§

impl Send for DirFS

§

impl Sync for DirFS

§

impl Unpin for DirFS

§

impl UnsafeUnpin for DirFS

§

impl UnwindSafe for DirFS

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.