Skip to main content

ReadStorage

Trait ReadStorage 

Source
pub trait ReadStorage {
    // Required methods
    fn read(&self, path: &Path) -> impl Future<Output = Result<Vec<u8>, Error>>;
    fn read_to_string(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<String, Error>>;
    fn read_dir(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<Vec<DirEntry>, Error>>;
    fn metadata(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<Metadata, Error>>;

    // Provided methods
    fn try_exists(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<bool, Error>> { ... }
    fn executable(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<Option<bool>, Error>> { ... }
    fn read_link(
        &self,
        path: &Path,
    ) -> impl Future<Output = Result<Option<PathBuf>, Error>> { ... }
}
Expand description

The read half of an async filesystem backend: everything the traversal core needs, and nothing that can change a byte on disk.

The split from Storage is not decoration — it is what lets a tree be depended on by a consumer that must not, and cannot, write: a language server, a renderer, a browser viewer. A backend that implements only this is a provably read-only view, checked by the compiler rather than by review.

Each method mirrors the std::fs function of the same name. try_exists has a default in terms of metadata.

Required Methods§

Source

fn read(&self, path: &Path) -> impl Future<Output = Result<Vec<u8>, Error>>

Read the entire contents of a file as bytes. Mirrors std::fs::read.

Source

fn read_to_string( &self, path: &Path, ) -> impl Future<Output = Result<String, Error>>

Read the entire contents of a file as a string. Mirrors std::fs::read_to_string.

Source

fn read_dir( &self, path: &Path, ) -> impl Future<Output = Result<Vec<DirEntry>, Error>>

Return the entries in a directory (non-recursive). Mirrors std::fs::read_dir, but yields a Vec since async iterators are not yet stable.

Source

fn metadata(&self, path: &Path) -> impl Future<Output = Result<Metadata, Error>>

Return metadata about the entry at path. Mirrors std::fs::metadata; follows symlinks.

Provided Methods§

Source

fn try_exists(&self, path: &Path) -> impl Future<Output = Result<bool, Error>>

Returns Ok(true) if the path exists, Ok(false) if it does not, and Err(_) if the check itself failed. Mirrors std::fs::try_exists.

Source

fn executable( &self, path: &Path, ) -> impl Future<Output = Result<Option<bool>, Error>>

Whether the file at path can be run — or None where that is not a thing this backend has.

None is the load-bearing answer, and it is declined, never guessed: a backend that cannot observe the bit — Windows, InMemoryFs, a document provider handing over opaque blobs — must not answer false, because “not executable” and “I do not model this” are different facts, and a consumer restoring modes across two machines must be able to tell them apart rather than take turns flipping a bit neither can see. The default is the decline, so a backend with no opinion is already correct.

Follows symlinks, like metadata.

What the symbolic link at path points at, read rather than followed — or None where this backend models no links at all. Mirrors std::fs::read_link, with the decline folded in.

Ok(None) is reserved for the decline, exactly as executable’s is: it means there is no such thing here, it is the default’s answer, and an implementation that does model links must never give it. Such an implementation answers with the target, or with an error where the path holds no link — which is what readlink already does, and what lets one call settle whether links exist at all. Reading the link is what makes recording one safe; following it would make the thing at the other end look like a file of this tree.

Dyn Compatibility§

This trait is not dyn compatible.

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

Implementations on Foreign Types§

Source§

impl<S> ReadStorage for &S
where S: ReadStorage + ?Sized,

A borrowed ReadStorage is itself a ReadStorage — so an owned backend can be lent to something generic over S: ReadStorage without moving it or wrapping it in an Arc the caller doesn’t otherwise need.

Every member is forwarded explicitly. The matching Storage forwarding below does the same for the durability members, where leaving any to inherit the trait’s defaults would silently downgrade a real backend’s guarantees the moment it was borrowed.

Source§

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

Source§

async fn read_to_string(&self, path: &Path) -> Result<String, Error>

Source§

async fn read_dir(&self, path: &Path) -> Result<Vec<DirEntry>, Error>

Source§

async fn metadata(&self, path: &Path) -> Result<Metadata, Error>

Source§

async fn try_exists(&self, path: &Path) -> Result<bool, Error>

Source§

async fn executable(&self, path: &Path) -> Result<Option<bool>, Error>

Source§

impl<S> ReadStorage for Arc<S>
where S: ReadStorage + ?Sized,

An Arc<S> is itself a ReadStorage on the same terms as &S above — so a backend shared across several owners (several open handles, a multi-tab web client) still carries its real capabilities through the Arc, rather than an adapter that forgot to unwrap it silently degrading to the pessimistic defaults.

Arc<S> derefs to S exactly like &S does, so the same explicit, every-member forwarding applies for the same reason: the trait’s defaults must never be reached by accident.

Source§

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

Source§

async fn read_to_string(&self, path: &Path) -> Result<String, Error>

Source§

async fn read_dir(&self, path: &Path) -> Result<Vec<DirEntry>, Error>

Source§

async fn metadata(&self, path: &Path) -> Result<Metadata, Error>

Source§

async fn try_exists(&self, path: &Path) -> Result<bool, Error>

Source§

async fn executable(&self, path: &Path) -> Result<Option<bool>, Error>

Implementors§