Skip to main content

VfsiExt

Trait VfsiExt 

Source
pub trait VfsiExt: Vfsi {
Show 47 methods // Provided methods fn open_options(&self) -> OpenOptions<'_, Self> { ... } fn statfs<P>(&self, target: P) -> Result<FilesystemStats, VfError> where P: AsTarget<Self::File> { ... } fn open(&self, path: impl AsRef<Path>) -> Result<Self::File, VfError> { ... } fn create(&self, path: impl AsRef<Path>) -> Result<Self::File, VfError> { ... } fn open_with(&self, request: OpenOp<'_>) -> Result<Self::File, VfError> { ... } fn close_files(&self, files: Vec<Self::File>) -> Result<(), VfError> { ... } fn read(&self, path: impl AsRef<Path>) -> Result<Vec<u8>, VfError> { ... } fn read_with_options( &self, path: impl AsRef<Path>, options: ReadOptions, ) -> Result<Vec<u8>, VfError> { ... } fn read_files<P>(&self, paths: &[P]) -> Result<Vec<Vec<u8>>, VfError> where P: AsRef<Path> { ... } fn read_files_with_options<P>( &self, paths: &[P], options: ReadOptions, ) -> Result<Vec<Vec<u8>>, VfError> where P: AsRef<Path> { ... } fn read_to_string(&self, path: impl AsRef<Path>) -> Result<String, VfError> { ... } fn read_to_string_with_options( &self, path: impl AsRef<Path>, options: ReadOptions, ) -> Result<String, VfError> { ... } fn read_stream( &self, path: impl AsRef<Path>, callback: impl FnMut(u64, &[u8]) -> Result<ControlFlow<()>, VfError>, ) -> Result<StreamCompletion, VfError> { ... } fn read_stream_with_options( &self, path: impl AsRef<Path>, options: StreamOptions, callback: impl FnMut(u64, &[u8]) -> Result<ControlFlow<()>, VfError>, ) -> Result<StreamCompletion, VfError> { ... } fn write(&self, path: impl AsRef<Path>, data: &[u8]) -> Result<(), VfError> { ... } fn write_files<P, B>(&self, entries: &[(P, B)]) -> Result<(), VfError> where P: AsRef<Path>, B: AsRef<[u8]> { ... } fn std_io<'a>( &'a self, file: &'a Self::File, ) -> impl Read + Write + Seek + 'a { ... } fn sync_data(&self, file: &Self::File) -> Result<(), VfError> { ... } fn sync_all(&self, file: &Self::File) -> Result<(), VfError> { ... } fn attrs<T>(&self, path: T) -> Result<Attrs, VfError> where T: AsTarget<Self::File> { ... } fn attrs_with_options<T>( &self, path: T, options: AttrsOptions, ) -> Result<Attrs, VfError> where T: AsTarget<Self::File> { ... } fn symlink_attrs(&self, path: impl AsRef<Path>) -> Result<Attrs, VfError> { ... } fn read_dir(&self, path: impl AsRef<Path>) -> Result<Vec<DirEntry>, VfError> { ... } fn read_dir_with_options( &self, path: impl AsRef<Path>, options: ListDirOptions, ) -> Result<Vec<DirEntry>, VfError> { ... } fn read_dirs<P>( &self, paths: &[P], ) -> Result<Vec<DirectoryListing>, VfError> where P: AsRef<Path> { ... } fn read_dirs_with_options<P>( &self, paths: &[P], options: ListDirOptions, ) -> Result<Vec<Vec<DirectoryListing>>, VfError> where P: AsRef<Path> { ... } fn listdir( &self, root: impl AsRef<Path>, options: impl Into<WalkOptions>, visitor: impl FnMut(&WalkEvent) -> Result<WalkControl, VfError>, ) -> Result<TraversalCompletion, VfError> { ... } fn visit_entries_with_options<P>( &self, paths: &[P], options: ListDirOptions, callback: impl FnMut(usize, &DirEntry) -> Result<ControlFlow<()>, VfError>, ) -> Result<Vec<TraversalCompletion>, VfError> where P: AsRef<Path> { ... } fn visit_dirs_ordered( &self, root: impl AsRef<Path>, options: ListDirOptions, order: impl FnMut(&DirEntry, &DirEntry) -> Ordering, descend: impl FnMut(&DirEntry) -> bool, visitor: impl FnMut(DirectoryListing, usize) -> Result<WalkControl, VfError>, ) -> Result<TraversalCompletion, VfError> { ... } fn create_dir(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn truncate<T>(&self, target: T, len: u64) -> Result<(), VfError> where T: AsTarget<Self::File> { ... } fn chmod<T>( &self, target: T, permissions: Permissions, ) -> Result<(), VfError> where T: AsTarget<Self::File> { ... } fn chown<T>( &self, target: T, uid: Option<u32>, gid: Option<u32>, ) -> Result<(), VfError> where T: AsTarget<Self::File> { ... } fn create_dir_with_mode( &self, path: impl AsRef<Path>, mode: u32, ) -> Result<(), VfError> { ... } fn symlink( &self, target: impl AsRef<Path>, link: impl AsRef<Path>, ) -> Result<(), VfError> { ... } fn read_link(&self, path: impl AsRef<Path>) -> Result<PathBuf, VfError> { ... } fn hard_link( &self, source: impl AsRef<Path>, link: impl AsRef<Path>, ) -> Result<(), VfError> { ... } fn create_dir_all(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn rename( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, ) -> Result<(), VfError> { ... } fn copy( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, ) -> Result<(), VfError> { ... } fn copy_with_options( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, options: CopyOptions, ) -> Result<(), VfError> { ... } fn remove_file(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn remove_dir(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn remove_dir_all(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn remove_dir_all_with_options( &self, path: impl AsRef<Path>, options: RemoveOptions, ) -> Result<(), VfError> { ... } fn remove_dir_contents(&self, path: impl AsRef<Path>) -> Result<(), VfError> { ... } fn remove_dir_contents_with_options( &self, path: impl AsRef<Path>, options: RemoveOptions, ) -> Result<(), VfError> { ... }
}
Expand description

Scalar operations and convenience workflows alongside the Vfsi vectors.

Blanket-implemented for every filesystem implementing Vfsi. Import VfsiExt (or crate::api::prelude) to use these helpers; generic code needs only an Vfsi bound. Helpers preserve batching, resource limits, and non-atomic failure semantics. All helpers compose vectorized Vfsi primitives; native execution belongs in Vfsi. Single-target helpers use conventional names such as open, attrs, and read_dir. Prefer vector APIs for independent work on many files or directories so the backend can batch requests.

§Method groups

§Boundary

ContractResponsibilityExamples
VfsiNative vector execution, paging, and policy inspectionvopen, vread, vlistdirs, limits
VfsiExtScalar adapters and composed workflowsopen, read_files, create_dir_all

Implement only Vfsi; this extension is blanket implemented. A helper belongs here only when it can compose Vfsi primitives without losing native batching, bounded paging, or recovery semantics. Singular convenience is not a promise of one RPC, and vector execution is not a promise of atomicity.

Provided Methods§

Source

fn open_options(&self) -> OpenOptions<'_, Self>

Build reusable open options for this client.

Source

fn statfs<P>(&self, target: P) -> Result<FilesystemStats, VfError>
where P: AsTarget<Self::File>,

Query one target through the vector filesystem-statistics engine.

Source

fn open(&self, path: impl AsRef<Path>) -> Result<Self::File, VfError>

Single-target convenience. For multiple files, prefer Vfsi::vopen to expose batching opportunities.

Open read-only. Paths are relative to this client’s configured namespace.

Use open_with for write/create flags, or vopen to batch many opens. The returned handle owns lifecycle only; use vectors or std_io for I/O.

use vfsi_core::api::{Vfsi, VfsiExt, FileHandle, WriteOp};
let file = fs.open("/config")?;
let mut header = [0_u8; 128];
let result = fs.vread([vfsi_core::api::ReadOp::into(&file, 0, &mut header)], Default::default());
let close = file.close();
let bytes = result?[0].bytes_read();
close?;
println!("read {bytes} bytes");
Source

fn create(&self, path: impl AsRef<Path>) -> Result<Self::File, VfError>

Single-target convenience. For multiple creations, prefer Vfsi::vopen with CREATE/TRUNCATE flags.

Create or truncate a file and open for writing; does not create parents.

Existing contents are discarded immediately. For exclusive creation, use open_with with WRITE | CREATE_NEW instead.

use vfsi_core::api::{Vfsi, VfsiExt, FileHandle, WriteOp};
let file = fs.create("/output")?;
let result = fs.vwrite(&[WriteOp::at(&file, 0, b"complete contents")], vfsi_core::api::WriteOptions::new().with_write_all(true));
let close = file.close();
result?;
close?;
Source

fn open_with(&self, request: OpenOp<'_>) -> Result<Self::File, VfError>

Single-target convenience. For multiple requests, prefer Vfsi::vopen with per-file flags and modes.

Open with an explicit access/create/truncate request; effects are eager.

Creation/truncation occurs at open, not on the first write. CREATE_NEW rejects an existing path. This does not create missing parents. Delegates to singleton Vfsi::vopen. Backends must preserve scalar final- symlink resolution and independently opened handles for singleton vectors.

use vfsi_core::api::{Vfsi, VfsiExt, FileHandle, OpenFlags, OpenOp, WriteOp};
let file = fs.open_with(OpenOp::new(
    "/new-file", OpenFlags::WRITE | OpenFlags::CREATE_NEW,
).mode(0o600))?;
file.close()?;
Source

fn close_files(&self, files: Vec<Self::File>) -> Result<(), VfError>

Consume all handles. Errors cannot return cleanup ownership; Drop is best-effort. Prefer vclose when close errors require reconciliation.

This releases all local handles even on failure; it does not promise every remote CLOSE succeeded. Closing alone is not a durability barrier.

use vfsi_core::api::{Vfsi, VfsiExt, OpenFlags, OpenOp, WriteOp};
let files = fs.vopen(&[OpenOp::new("/config", OpenFlags::READ)])?;
fs.close_files(files)?; // Observe a close error instead of discarding it in Drop.
Source

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

Read one complete file within the client’s aggregate read budget.

For multiple files, prefer Self::read_files. This is a convenience over the vector read operation and retains its allocation limits.

Source

fn read_with_options( &self, path: impl AsRef<Path>, options: ReadOptions, ) -> Result<Vec<u8>, VfError>

Read one complete file with an explicit read policy.

Source

fn read_files<P>(&self, paths: &[P]) -> Result<Vec<Vec<u8>>, VfError>
where P: AsRef<Path>,

Read complete files in input order using vectorized whole-file reads.

The aggregate payload is bounded by limits().max_read_bytes(). Use Self::read_files_with_options to override it, or stream large files. A failure returns an error, not a successful partial collection.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let contents = fs.read_files(&["/file-1", "/file-2"])?;
for bytes in contents { println!("{} bytes", bytes.len()); }
Source

fn read_files_with_options<P>( &self, paths: &[P], options: ReadOptions, ) -> Result<Vec<Vec<u8>>, VfError>
where P: AsRef<Path>,

Whole-file convenience reads with an explicit aggregate payload budget.

use vfsi_core::api::{Vfsi, VfsiExt, ReadOptions, WriteOp};
let files = fs.read_files_with_options(&["/config"],
    ReadOptions::new().with_max_total_bytes(std::num::NonZeroUsize::new(1024 * 1024).unwrap()))?;
Source

fn read_to_string(&self, path: impl AsRef<Path>) -> Result<String, VfError>

Single-target convenience. For multiple files, prefer Vfsi::vread with whole-file operations and decode each result as UTF-8.

Read a complete UTF-8 file within this client’s aggregate read budget.

Invalid UTF-8 is an invalid-input error; use read_files for arbitrary bytes.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let text = fs.read_to_string("/config")?;
println!("{text}");
Source

fn read_to_string_with_options( &self, path: impl AsRef<Path>, options: ReadOptions, ) -> Result<String, VfError>

Single-target convenience. For multiple files, prefer Vfsi::vread with an aggregate byte budget, then decode UTF-8.

Read a complete UTF-8 file with the same budget policy as Vfsi::vread. ReadOptions::default() inherits the client limit; explicit overrides are nonzero.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let text = fs.read_to_string_with_options("/config", vfsi_core::api::ReadOptions::new()
    .with_max_total_bytes(std::num::NonZeroUsize::new(4096).unwrap()))?;
println!("{text}");
Source

fn read_stream( &self, path: impl AsRef<Path>, callback: impl FnMut(u64, &[u8]) -> Result<ControlFlow<()>, VfError>, ) -> Result<StreamCompletion, VfError>

Single-target convenience. For multiple files, prefer Vfsi::vstream. Backends may process streams sequentially.

Stream a file using the client’s bounded chunk size instead of collecting it. Return Ok(ControlFlow::Break(())) to stop successfully; the callback runs outside the lock.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.read_stream("/large", |offset, bytes| {
    println!("{} bytes at {offset}", bytes.len());
    Ok(std::ops::ControlFlow::Continue(()))
})?;
Source

fn read_stream_with_options( &self, path: impl AsRef<Path>, options: StreamOptions, callback: impl FnMut(u64, &[u8]) -> Result<ControlFlow<()>, VfError>, ) -> Result<StreamCompletion, VfError>

Single-target convenience. For multiple files, prefer Vfsi::vstream. Backends may process streams sequentially.

Stream from offset zero outside the backend lock. ControlFlow::Break(()) stops after the delivered chunk; completion reports the next offset. Not a snapshot.

The callback borrows each chunk only for its invocation. Consume it without collecting chunks to keep memory bounded. chunk_size is a maximum; negotiated protocol limits and short reads can produce smaller chunks. The internally opened file is closed on completion, stopping, callback error, or read failure. Stopping successfully does not mean EOF. This simple stream does not promise RTT-hiding parallelism; direct NFS applications can use NfsBuilder::connect_read_pool for pipelined reads.

use vfsi_core::api::{Vfsi, VfsiExt, StreamOptions, StreamCompletion, WriteOp};
let mut processed = 0_u64;
let completion = fs.read_stream_with_options(
    "/large.bin", StreamOptions::new().with_chunk_size(std::num::NonZeroUsize::new(1024 * 1024).unwrap()),
    |_offset, chunk| {
        processed += chunk.len() as u64; // Process the borrowed bytes here.
        Ok(if processed < 8 * 1024 * 1024 {
            std::ops::ControlFlow::Continue(())
        } else {
            std::ops::ControlFlow::Break(())
        }) // Stop after a bounded sample.
    },
)?;
match completion {
    StreamCompletion::Complete => println!("reached EOF after {processed} bytes"),
    StreamCompletion::Stopped { next_offset } => println!("stopped at {next_offset}"),
}
Source

fn write(&self, path: impl AsRef<Path>, data: &[u8]) -> Result<(), VfError>

Single-target convenience. For multiple complete files, prefer VfsiExt::write_files; for opened handles, prefer Vfsi::vwrite.

Replace a file completely, creating/truncating eagerly; not atomic replace.

The parent must exist. Success writes all bytes and closes the internal handle; failure may leave a created, truncated, or partially written file. For exclusive creation or durability control use an explicit open handle.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.write("/output", b"replacement contents")?;
Source

fn write_files<P, B>(&self, entries: &[(P, B)]) -> Result<(), VfError>
where P: AsRef<Path>, B: AsRef<[u8]>,

Replace files in vector phases. Success completes payloads; errors may follow create/truncate/write effects and never authorize blind replay.

Parents must exist. Payloads are completed via vector open/write/close phases, not a scalar write loop or necessarily a single RPC. No atomic replacement, cross-file transaction, or durability guarantee is provided.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.write_files(&[
    ("/file-1", b"hello".as_slice()),
    ("/file-2", b"world".as_slice()),
])?;
Source

fn std_io<'a>(&'a self, file: &'a Self::File) -> impl Read + Write + Seek + 'a

Borrow a standard-I/O adapter with an independent cursor, initially zero. Reads/writes use this client’s vectors; collecting reads enforce its payload budget. The adapter does not own or close the file.

Source

fn sync_data(&self, file: &Self::File) -> Result<(), VfError>

Synchronize one retained handle through Vfsi::vfsync.

Source

fn sync_all(&self, file: &Self::File) -> Result<(), VfError>

Synchronize one retained handle’s data and metadata through Vfsi::vfsync.

Source

fn attrs<T>(&self, path: T) -> Result<Attrs, VfError>
where T: AsTarget<Self::File>,

Single-target convenience. For multiple paths, prefer Vfsi::vgetattrs.

Query a path following its final symlink; unavailable fields remain None.

To inspect the symlink itself use symlink_attrs. To query an opened object after rename, pass crate::api::Target::file.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let attrs = fs.attrs("/file-1")?;
println!("{:?} bytes; directory={}", attrs.len(), attrs.is_dir());
Source

fn attrs_with_options<T>( &self, path: T, options: AttrsOptions, ) -> Result<Attrs, VfError>
where T: AsTarget<Self::File>,

Single-target convenience. For multiple paths, prefer Vfsi::vgetattrs with selected fields and follow_final_symlink(false).

Query one path with selected fields and final-symlink behavior; absent fields remain None.

This avoids requesting every optional attribute. Type/size can be requested internally even when not selected; missing optional attributes must still be handled via their Option accessors.

use vfsi_core::api::{Vfsi, VfsiExt, Attributes, WriteOp};
let attrs = fs.attrs_with_options(
    "/file-1", vfsi_core::api::AttrsOptions::new()
        .with_fields(Attributes::MODE | Attributes::BLOCKS).with_follow_final_symlink(false),
)?;
if let Some(blocks) = attrs.blocks() {
    println!("allocated blocks: {blocks}");
}

Single-target convenience. For multiple paths, prefer Vfsi::vgetattrs with follow_final_symlink(false).

Query the final symlink itself instead of following it.

This does not prevent following symlinks in ancestor components and is not a race-free namespace confinement primitive.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let attrs = fs.symlink_attrs("/link-or-file")?;
println!("symlink={}", attrs.is_symlink());
Source

fn read_dir(&self, path: impl AsRef<Path>) -> Result<Vec<DirEntry>, VfError>

Single-target convenience. For multiple directories, prefer VfsiExt::read_dirs_with_options or VfsiExt::read_dirs.

Collect one directory using the client’s entry and path-byte limits.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
for entry in fs.read_dir("/input")? {
    println!("{}", entry.path().display());
}
Source

fn read_dir_with_options( &self, path: impl AsRef<Path>, options: ListDirOptions, ) -> Result<Vec<DirEntry>, VfError>

Single-target convenience. For multiple directories, prefer VfsiExt::read_dirs_with_options with one aggregate budget.

Collect one shallow directory with selected metadata and entry/path-byte limits. Recursive options are rejected; use read_dirs_with_options with ListDirOptions::with_recursive(true) to collect a tree.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
let entries = fs.read_dir_with_options("/input",
    vfsi_core::api::ListDirOptions::new().with_max_entries(100))?;
println!("{} entries", entries.len());
Source

fn read_dirs<P>(&self, paths: &[P]) -> Result<Vec<DirectoryListing>, VfError>
where P: AsRef<Path>,

Collect directory listings under one aggregate entry/path-byte policy.

There is one listing per input directory, in input order; entry order is backend-defined. Entries include metadata, avoiding a separate scalar stat per child. The default policy comes from this client’s limits. Use read_dirs_with_options to select attributes, or a visitor instead of collecting large listings.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
for listing in fs.read_dirs(&["/input", "/output"])? {
    for entry in listing.entries {
        println!("{}: {:?} bytes", entry.path().display(), entry.attrs().len());
    }
}
Source

fn read_dirs_with_options<P>( &self, paths: &[P], options: ListDirOptions, ) -> Result<Vec<Vec<DirectoryListing>>, VfError>
where P: AsRef<Path>,

Collect shallow directories or recursive trees, grouped by input root.

results[i] contains the listings for paths[i]. Shallow mode returns exactly one listing per root; recursive mode includes the root and descendants. Entries and path-byte budgets are shared across roots; recursive collection also charges retained directory paths. Collection builds on the batched directory-page visitor. Explicit limits override client defaults. Errors discard collected results; this is not a snapshot. Symlink entries are not recursively followed.

use vfsi_core::api::{Vfsi, VfsiExt, Attributes, ListDirOptions};
let trees = fs.read_dirs_with_options(&["/input", "/output"],
    ListDirOptions::new().with_recursive(true).with_fields(Attributes::MODE)
        .with_max_entries(10_000).with_max_path_bytes(1024 * 1024))?;
for tree in trees {
    for listing in tree {
        println!("{}: {} entries", listing.path.display(), listing.entries.len());
    }
}
Source

fn listdir( &self, root: impl AsRef<Path>, options: impl Into<WalkOptions>, visitor: impl FnMut(&WalkEvent) -> Result<WalkControl, VfError>, ) -> Result<TraversalCompletion, VfError>

List one directory through callbacks, optionally recursively. For independent roots and owned pages, prefer Vfsi::vlistdirs.

By default, only child Entry events are delivered, with no extra root attribute request or full-listing allocation on paging backends. Set recursive(true) to descend without following entry symlinks. Entry-only traversal retains native anchored child cursors and sibling batching; its order is backend-defined.

enter_leave(true) includes the root and emits depth-first Enter and Leave events for traversed directories, including pruned directories. In shallow lifecycle mode, children are Entry events. Symlinks are always Entry events. A non-directory lifecycle root produces one Entry. Lifecycle traversal currently retains bounded directory buffers because the vector page primitive does not expose resumable cursors. sort_by_name(true) also buffers a bounded directory before sorting. Unsorted entry-only visiting remains paged. This is not a snapshot. Buffered recursive/lifecycle visiting rejects symlinks in reopened directory paths, including ancestors. Backends unable to guarantee that return Unsupported instead of checking and then following the path. Ordinary shallow listing retains the backend’s path resolution; use allow_symlink_components(false) to require no-follow directory opens explicitly.

The root is depth zero and its children have depth one. Directory depth limits control descent; shallow mode ignores them. Lifecycle mode charges the root against the entry/path budgets; recursive entry-only mode charges retained directory paths. All unspecified budgets inherit client limits.

SkipSubtree on Enter prevents reading that directory’s children; it does nothing on files or Leave. Pruning a recursive directory Entry without lifecycle events is rejected: enable enter_leave(true). Stop returns Stopped immediately, without synthesizing pending Leave events. Callback errors propagate without replay. Callbacks run outside backend locks and may reenter.

use vfsi_core::api::{ListDirOptions, Vfsi, VfsiExt, WalkControl};
fs.listdir("/input", ListDirOptions::new(), |event| {
    println!("{}", event.entry.path().display());
    Ok(WalkControl::Continue)
})?;

Recursive lifecycle events allow pruning before listing children:

use vfsi_core::api::{ListDirOptions, Vfsi, VfsiExt, WalkControl, WalkEventKind};
fs.listdir("/project",
    vfsi_core::api::WalkOptions::new(ListDirOptions::new().with_recursive(true))
        .with_enter_leave(true).with_sort_by_name(true),
    |event| {
        if event.kind == WalkEventKind::Enter
            && event.entry.file_name() == Some(std::ffi::OsStr::new(".git")) {
            return Ok(WalkControl::SkipSubtree);
        }
        println!("{:?}: {}", event.kind, event.entry.path().display());
        Ok(WalkControl::Continue)
    })?;
Source

fn visit_entries_with_options<P>( &self, paths: &[P], options: ListDirOptions, callback: impl FnMut(usize, &DirEntry) -> Result<ControlFlow<()>, VfError>, ) -> Result<Vec<TraversalCompletion>, VfError>
where P: AsRef<Path>,

Visit individual entries using the directory-page primitive. Empty directories produce pages but no entry callbacks.

Source

fn visit_dirs_ordered( &self, root: impl AsRef<Path>, options: ListDirOptions, order: impl FnMut(&DirEntry, &DirEntry) -> Ordering, descend: impl FnMut(&DirEntry) -> bool, visitor: impl FnMut(DirectoryListing, usize) -> Result<WalkControl, VfError>, ) -> Result<TraversalCompletion, VfError>

Visit complete shallow listings in depth-first order with application policy.

order compares immutable siblings (for example, locale-aware ls ordering). The shared workflow sorts them; callbacks cannot replace validated entries. descend selects directories before their contents are read; it does not filter entries delivered in their parent’s listing. Symlinks are never traversed. Descendant opens reject symlinks in every component; backends unable to guarantee that return Unsupported. The root uses the supplied path-resolution policy. visitor runs outside backend locks and may stop immediately or skip all children of the current directory. Errors after delivered listings must not trigger replay through another backend.

Storage is bounded by one complete listing and the pending directory frontier. Entry/path budgets charge all fetched children, including those rejected by descend. This ordered workflow deliberately does not speculatively list children before admission; use vlistdirs to batch already-approved independent directories.

use vfsi_core::api::{Attributes, Result, Vfsi, VfsiExt, WalkControl};
fs.visit_dirs_ordered("/input",
    fs.limits().walk_options().with_fields(Attributes::MODE | Attributes::SIZE),
    |a, b| a.path().cmp(b.path()),
    |entry| entry.file_name() != Some(std::ffi::OsStr::new(".git")),
    |listing, depth| {
        println!("{}: {} entries at depth {depth}", listing.path.display(), listing.entries.len());
        Ok(WalkControl::Continue)
    })?;
Source

fn create_dir(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple independent directories, prefer Vfsi::vmkdir.

Create one directory; its parent must exist.

An existing entry is an error, even if already a directory. Use create_dir_all for missing parents/idempotent directory setup, or vmkdir for independent siblings.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.create_dir("/fresh-directory")?;
Source

fn truncate<T>(&self, target: T, len: u64) -> Result<(), VfError>
where T: AsTarget<Self::File>,

Truncate or extend one path or opened object using Vfsi::vsetattrs.

Source

fn chmod<T>(&self, target: T, permissions: Permissions) -> Result<(), VfError>
where T: AsTarget<Self::File>,

Change permissions on one path or opened object using Vfsi::vsetattrs.

Source

fn chown<T>( &self, target: T, uid: Option<u32>, gid: Option<u32>, ) -> Result<(), VfError>
where T: AsTarget<Self::File>,

Change ownership of one path or opened object through Vfsi::vsetattrs. None leaves the corresponding owner/group unchanged. Use the vector with SetAttrsOp::with_follow_final_symlink(false) to change a symlink itself.

Source

fn create_dir_with_mode( &self, path: impl AsRef<Path>, mode: u32, ) -> Result<(), VfError>

Create one directory with explicit Unix permission bits.

Create one symbolic link; submit multiple pairs with Vfsi::vsymlink.

Read one symlink target; submit multiple paths with Vfsi::vreadlink.

Create one hard link; submit multiple pairs with Vfsi::vhardlink.

Source

fn create_dir_all(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple directory creations, prefer Vfsi::vmkdir; plan missing parents before their children.

Create missing parents; an error can leave some directories created.

Existing directories are accepted; an existing non-directory component is an error. This is not atomic and is not protected against concurrent changes to ancestor paths.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.create_dir_all("/workspace/results/2026")?;
Source

fn rename( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, ) -> Result<(), VfError>

Single-target convenience. For multiple source/destination pairs, prefer Vfsi::vrename.

Rename within supported namespaces; cross-filesystem moves can fail.

Both paths use this client’s namespace. Replacement semantics follow the backend/filesystem; this is not a cross-file vector transaction or a guarantee of durable directory updates. No copy fallback is implied.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.rename("/old-name", "/new-name")?;
Source

fn copy( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, ) -> Result<(), VfError>

Single-target convenience. For multiple file pairs, prefer Vfsi::vcopy.

Copy a file’s contents; this is not recursive tree copying.

Destination creation/replacement and failures follow backend semantics. A failure can leave a partial destination. Do not assume metadata, sparse layout, or durability is preserved. Server-side copy is used only where supported; callers need not build protocol COPY requests.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.copy("/source", "/destination")?;
Source

fn copy_with_options( &self, source: impl AsRef<Path>, destination: impl AsRef<Path>, options: CopyOptions, ) -> Result<(), VfError>

Single-target copy with explicit operation semantics; prefer Vfsi::vcopy when submitting multiple pairs.

Source

fn remove_file(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple paths, prefer Vfsi::vremove. That vector API accepts both files and directories.

Remove one file or symlink, not the symlink target.

Missing paths are errors. To remove a directory use remove_dir or remove_dir_all.

use vfsi_core::api::{Vfsi, VfsiExt, ErrorKind, WriteOp};
match fs.remove_file("/temporary-file") {
    Ok(()) => (),
    Err(error) if error.kind() == ErrorKind::NotFound => (),
    Err(error) => return Err(error),
}
Source

fn remove_dir(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple paths, prefer Vfsi::vremove. That vector API does not enforce directory-only inputs.

Remove one empty directory; not a recursive operation.

Nonempty directories fail. Use remove_dir_contents to empty a directory while retaining it, or remove_dir_all to remove its tree. Only operate on paths whose removal you intend.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.remove_dir("/empty-temporary-directory")?;
Source

fn remove_dir_all(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple trees, prefer Vfsi::vremove with RemoveMode::Tree.

Recursively remove a tree without following directory symlinks. Path-based removal is not a security sandbox or an atomic transaction.

A failure can leave a partly removed tree. Use trusted ancestor paths; concurrent namespace substitutions are not a confinement guarantee. This is destructive: do not use it to prepare an arbitrary existing directory for an example or benchmark.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
// Remove only the tree that this application intentionally owns.
fs.remove_dir_all("/owned-temporary-tree")?;
Source

fn remove_dir_all_with_options( &self, path: impl AsRef<Path>, options: RemoveOptions, ) -> Result<(), VfError>

Recursively remove one directory using explicit batching and failure policy. The directory is validated before mutation; symlink roots are not followed. Prefer Vfsi::vremove when removing several trees.

Source

fn remove_dir_contents(&self, path: impl AsRef<Path>) -> Result<(), VfError>

Single-target convenience. For multiple directory roots, prefer Vfsi::vremove.

Recursively empty a directory while keeping its root.

The root must be a directory, not a symlink. Child symlinks are removed without following their targets. Errors can leave partially removed contents; retaining the root does not make the operation transactional. The path is resolved for this call, not pinned across calls or renames. Use trusted ancestors; this is not a path-confinement guarantee.

use vfsi_core::api::{Vfsi, VfsiExt, WriteOp};
fs.remove_dir_contents("/owned-scratch-directory")?;
// The scratch directory remains available for subsequent work.
Source

fn remove_dir_contents_with_options( &self, path: impl AsRef<Path>, options: RemoveOptions, ) -> Result<(), VfError>

Recursively empty one directory while retaining its root, using explicit batching and failure policy. The root is validated without following a symlink. Prefer Vfsi::vremove for several roots. Like Self::remove_dir_contents, this resolves the current pathname; it does not retain a previously opened directory’s identity.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<C> VfsiExt for C
where C: Vfsi + ?Sized,