pub enum WriteValue {
Intercepted {
at: StorePath,
said: SmolStr,
},
Refused {
at: StorePath,
said: SmolStr,
},
Recursed {
at: StorePath,
},
Absent {
at: StorePath,
},
NotAPath(StorePathError),
TooDeep {
at: StorePath,
why: Because,
},
WillNotEncode {
at: StorePath,
why: Because,
},
Closed {
at: StorePath,
},
SourceGone,
Store(Because),
}Expand description
Everything a write through a reactive primitive can fail with, and nothing else.
Fields, cells and maps fail in the same ways, so they share one set; the per-primitive names below are aliases kept for readability at call sites.
Ordinary std::error::Error, so a caller who does not want to look can
? it into anyhow, eyre or a Box<dyn Error> and be done - and get the
whole diagnosis out of it. Display says what this write
was and where; source descends through the
contexts under it, each carrying what was attached to it, so a
{:?} of an anyhow::Error names the operation, the key, the file and the
engine’s own words without a match anywhere.
A caller who wants a fact as a type rather than as a sentence reads it back
with facts::all over the report the variant carries -
facts::all::<StoreFile, _>(why) for the file, Key for the key. That is
the typed way in; the chain is the readable one.
{:?} prints the same thing anyhow prints, because that is the shape a
reader has learnt: fn main() -> anyhow::Result<()> renders with Debug,
and so does every tracing::error!("{err:?}"). What the report holds beyond
the chain - the frame each context was raised at - is in
explain, which is where a dump belongs.
Variants§
Intercepted
An interceptor turned the change down, in its own words.
Refused
A rule declared on the field turned the value down, in its own words.
Recursed
Interceptors wrote back into the value they guard, nested deeper than a write may go, and the guard stopped them.
Nothing turned the change down - a rule that refuses is
Intercepted. This is a loop in the interceptors
themselves.
Absent
Nothing is stored where the write was aimed, and this write only changes what is already there.
NotAPath(StorePathError)
The name handed in cannot be a level, so nothing can sit under it.
TooDeep
The path or the value nests deeper than this store reads back.
why is kept whole because the numbers are the diagnosis: which budget
ran out, what it was, and how much the path had already spent are
attached to it.
WillNotEncode
The value will not turn into what the store keeps, with what the codec said kept whole.
Closed
The store has let go of its file, so nothing lands.
No report, because there is never one to keep: every
StorageError::Closed is minted fresh at the refusal - the store
checks whether it is closed and answers - so nothing has failed
underneath. What the report did carry is the store’s own file, and that
is dropped here rather than lost from somewhere deeper.
SourceGone
The field or map this cell views has been dropped. into_cell is the
form that keeps it alive.
Store(Because)
The disk, in every sense: the file, the engine, the codec.
Carries the report whole, so the facts attached along the way - the key, the table, how many bytes - are still there for whoever wants them.
Implementations§
Source§impl WriteValue
impl WriteValue
Sourcepub fn from_store(at: &StorePath, why: Report<StorageError>) -> Self
pub fn from_store(at: &StorePath, why: Report<StorageError>) -> Self
What the store said, told apart where a caller would act on it differently.
Sourcepub fn explain(&self) -> String
pub fn explain(&self) -> String
The whole report as a string, facts and all, for a caller
handing this to anyhow: .context(why.explain()).
The chain source walks is the
readable half and is usually enough. This is the rest of it -
every frame, every attachment, laid out the way the report
renders itself - for a log record that has to carry everything.
Source§impl WriteValue
impl WriteValue
Sourcepub fn from_backend<E>(
at: &StorePath,
doing: StorageError,
why: Report<E>,
) -> Self
pub fn from_backend<E>( at: &StorePath, doing: StorageError, why: Report<E>, ) -> Self
The same, for a backend whose failures are its own rather than the
store’s - a client talking to one over a wire. doing is the operation
the wire was carrying, and what the transport said is the frame below.
Sourcepub fn intercepted(at: &StorePath, said: impl AsRef<str>) -> Self
pub fn intercepted(at: &StorePath, said: impl AsRef<str>) -> Self
The refusal an interceptor gave.
Trait Implementations§
Source§impl Debug for WriteValue
impl Debug for WriteValue
Source§impl Display for WriteValue
impl Display for WriteValue
Source§impl Error for WriteValue
impl Error for WriteValue
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<Report<StorageError>> for WriteValue
impl From<Report<StorageError>> for WriteValue
Source§fn from(why: Report<StorageError>) -> Self
fn from(why: Report<StorageError>) -> Self
Source§impl From<StorePathError> for WriteValue
impl From<StorePathError> for WriteValue
Source§fn from(why: StorePathError) -> Self
fn from(why: StorePathError) -> Self
Source§impl From<WriteValue> for Report<StorageError>
Back into a report, for the plumbing under the boundary.
impl From<WriteValue> for Report<StorageError>
Back into a report, for the plumbing under the boundary.
The sets are what a caller outside the library meets; inside it, everything
still travels as a report, and this is what lets a ? cross from one to
the other without a map_err at every line.