pub trait StorageAdapter:
Debug
+ Send
+ Sync {
// Required methods
fn read_text<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn write_text<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn write_text_if_absent<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn exists<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn rename_text<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
from_uri: &'life1 str,
to_uri: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn list_dir<'life0, 'life1, 'async_trait>(
&'life0 self,
dir_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn read_text_versioned<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(String, String)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn write_text_if_match<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
expected_version: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn delete_prefix<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
}Required Methods§
fn read_text<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn write_text<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Sourcefn write_text_if_absent<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn write_text_if_absent<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Write a text object only if no object exists at uri.
Returns Ok(true) when this call created the object, Ok(false)
when the object already existed, and propagates every other storage
error. Callers use this to establish ownership before running
best-effort cleanup on partial failure.
fn exists<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sourcefn rename_text<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
from_uri: &'life1 str,
to_uri: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn rename_text<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
from_uri: &'life1 str,
to_uri: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Move a file from from_uri to to_uri, replacing any existing file at
to_uri. Atomic on local POSIX; on S3 implemented as copy + delete
(NOT atomic — callers that depend on atomicity for crash recovery must
tolerate “both source and destination exist after a crash”).
Sourcefn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Remove a file. Returns Ok(()) if the file does not exist.
Sourcefn list_dir<'life0, 'life1, 'async_trait>(
&'life0 self,
dir_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_dir<'life0, 'life1, 'async_trait>(
&'life0 self,
dir_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
List all files (non-recursively, files only) directly under dir_uri.
Returns full URIs (same scheme as dir_uri). The result is unordered.
Returns Ok(empty) if the directory does not exist or is empty.
Consumers must tolerate non-payload residue appearing in storage
(backend staging files are filtered by the backend, but crash residue
of any future producer may not be) — filter by suffix, never assume
every entry is yours.
Sourcefn read_text_versioned<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(String, String)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read_text_versioned<'life0, 'life1, 'async_trait>(
&'life0 self,
uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(String, String)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Read a text object together with its backend version token (stores
with conditional-update support: the object’s ETag; local: sha256 of
the content). The token is opaque — valid only for
write_text_if_match against the same adapter.
Sourcefn write_text_if_match<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
expected_version: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn write_text_if_match<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
uri: &'life1 str,
contents: &'life2 str,
expected_version: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Replace the object at uri only if its current version still matches
expected_version (obtained from a prior versioned read/write on this
adapter). Returns Ok(Some(new_version)) on success and Ok(None)
when the precondition failed (a concurrent writer won — the CAS-lost
case callers must surface, never swallow). Stores with conditional
updates (S3, in-memory) use a true conditional put (If-Match); the
local filesystem has no such primitive (PutMode::Update is
unimplemented upstream), so local compares content then replaces via
an atomic staged write — the same single-machine semantics the
callers had before this trait, safe under the callers’ own lock
protocol but not a cross-process barrier by itself (see the Known
Gaps entry in docs/dev/invariants.md).
Sourcefn delete_prefix<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_prefix<'life0, 'life1, 'async_trait>(
&'life0 self,
prefix_uri: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Recursively delete every object under prefix_uri. Returns Ok(())
when nothing exists there (idempotent). Local: remove_dir_all
(directories are a local-FS concept; list+delete would leave empty
directory skeletons that local existence probes report as present);
object stores: list + delete (NOT atomic — callers must tolerate
partial prefixes on crash, which the cluster delete protocol does by
retry).
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".