pub struct MapFS { /* private fields */ }Expand description
A virtual file system (VFS) implementation that stores file and directory entries in memory using a hierarchical map structure.
MapFS provides a POSIX‑like file system interface where all data is kept in‑process,
allowing operations such as file creation, directory traversal, path resolution, and metadata
inspection without touching the host filesystem.
§Internal state
-
root— An absolute, normalized path associated with the host that serves as the physical anchor of the virtual file system (VFS). It has no effect on VFS operation under typical usage scenarios. This path determines how virtual paths are mapped to host paths (e.g., for synchronization or persistent storage layers).- Must be absolute and normalized (no
.., no redundant separators). - Example:
/tmp/my_vfs_rooton Unix,C:\\vfs\\rooton Windows.
- Must be absolute and normalized (no
-
cwd— Current Working Directory, expressed as an inner absolute normalized path within the virtual file system.- Determines how relative paths (e.g.,
docs/file.txt) are resolved. - Always starts with
/(or\on Windows) and is normalized. - Default value:
/(the virtual root). - Changed via methods like
cd().
- Determines how relative paths (e.g.,
-
entries— The core storage map that holds all virtual file and directory entries.- Key:
PathBufrepresenting inner absolute normalized paths (always start with/). - Value:
Entrystruct containing type, metadata, and (for files) content.
- Key:
§Invariants
- Root existence: The path
/is always present inentriesand has typeDirectory. - Path normalization: All keys in
entries, as well ascwdandroot, are normalized (no.., no//, trailing/removed except for root). - Parent consistency: For any entry at
/a/b/c, there must exist an entry/a/bof typeDirectory(except for the root/). - Uniqueness: No duplicate paths; each path maps to exactly one
Entry.
§Lifecycle
- On creation:
rootandcwdis set to/. If you want, you may setrootto a user‑supplied host path; - As files/directories are added via methods (e.g.,
mkfile(),mkdir(),add()), they are inserted intoentrieswith inner absolute paths. - Path resolution (e.g., in
is_file(),ls()) combinescwdwith input paths to produce inner absolute paths before queryingentries.
§Thread Safety
This struct is not thread‑safe by default. If concurrent access is required, wrap it in
a synchronization primitive (e.g., Arc<Mutex<MapFS>> or RwLock<MapFS>) at the application level.
§Example
let fs = MapFS::new();
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§
Trait Implementations§
Source§impl FsBackend for MapFS
impl FsBackend for MapFS
Source§fn to_host<P: AsRef<Path>>(&self, inner_path: P) -> Result<PathBuf>
fn to_host<P: AsRef<Path>>(&self, inner_path: P) -> Result<PathBuf>
Returns a hypothetical “host-path” joining root and inner_path.
inner_pathmust exist in VFS
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 in VFS. 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 in relative or absolute form.
Source§fn ls<P: AsRef<Path>>(&self, path: P) -> Result<impl Iterator<Item = &Path>>
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 path in fs.ls("/").unwrap() {
println!("{:?}", path);
}
// List contents of "/docs"
for path in fs.ls("/docs").unwrap() {
if path.is_file() {
println!("File: {:?}", path);
} else {
println!("Dir: {:?}", path);
}
}§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: P) -> Result<impl Iterator<Item = &Path>>
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
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:
fs.mkdir("/docs/subdir");
fs.mkfile("/docs/document.txt", None);
// Iterate over current working directory
for path in fs.tree("/").unwrap() {
println!("{:?}", path);
}
// Iterate over a specific directory
for path in fs.tree("/docs").unwrap() {
if path.is_file() {
println!("File: {:?}", path);
}
}§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
MapFSmethods (e.g.,is_file(),is_dir()) for 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 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>>
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)
- 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>>(&mut self, path: P, content: &[u8]) -> Result<()>
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)
- File does not exist in VFS (
§Behavior
- Overwrites completely: The entire existing content is replaced.
- No file creation: File must exist (use
mkfile()first).
Source§fn append<P: AsRef<Path>>(&mut self, path: P, content: &[u8]) -> Result<()>
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)
- File does not exist in VFS (
§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).
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;