Expand description
This library provides Error<S = Stateless>, an optionally dynamic dispatched error type,
enabling applications to handle errors uniformly across different contexts.
§Quick Start
In most cases, Error can serve as a drop-in replacement for Box<dyn Error>.
Compared to the latter, it occupies only 1 usize, making the happy path faster.
use erratic::*;
fn write_log(filename: String) -> Result<()> {
File::open(&filename)?.write_all(b"Hello, World!")?;
Ok(())
}§Attaching Context & Payload
When constructing an error, you can optionally attach a static context and/or a dynamic payload. If attached, their memory is merged into a single allocation when the upstream error is erased. If omitted, no extra memory is allocated for them. If only a context is provided, no heap allocation occurs at all.
use erratic::*;
fn write_log(filename: String) -> Result<()> {
File::open(&filename)
.ok()
.with_context(literal!("failed to open the log file"))? // No alloc.
.write_all(b"Hello, World!")
.with_context(literal!("while writing to"))
.with_payload(filename)?; // Alloc once for `io::Error`, `filename`, and `Context`.
Ok(())
}§Binding State
When propagating an error that requires special handling, you can attach a generic state
to it. The state is optional and can be cheaply erased or extracted using extract_state.
When the state is small enough and none of the source error, context, or payload is attached, the state is inlined without any heap allocation.
use erratic::*;
#[derive(Debug)]
enum WriteLog {
FileNotFound,
}
fn write_log(filename: String) -> std::result::Result<(), Error<WriteLog>> {
File::open(&filename)
.ok()
.with_state(WriteLog::FileNotFound)? // No alloc.
.write_all(b"Hello, World!")
.with_context(literal!("while writing to"))
.with_payload(filename)?;
Ok(())
}§Representation
Type-wise, Error<S> is an internally tagged union, and it requires pointers to constant or
heap-allocated data to be aligned to 4 bytes, freeing up the lower 2 bits to encode
the discriminant. This design allows heap allocation to be avoided when unnecessary.
(32-bit platform, little-endian)
(Context Only)
[XXXXXX00|XXXXXXXX|XXXXXXXX|XXXXXXXX]
\
`rodata-> [Context]
(State Only)
[00000010| ~ State ~ ]
(Otherwise)
[XXXXXX01|XXXXXXXX|XXXXXXXX|XXXXXXXX]
\
`heap-> [VTable|State|Error|Payload|Context]Modules§
- context
- Context traits and its placeholder for
Builder. - nae
- Error placeholder for
Builder. - payload
- Payload placeholder for
Builder. - state
- State traits and the
Statelessmarker.
Macros§
- literal
- Creates a literal value, or declares one or more named literal types.
- match_
else - Like
let-else, but also handles the remaining cases — forResultonly. - mkerr
- Constructs an
Errorfrom a variety of input types. - mkres
- Shorthand for
Err(mkerr!(..)).
Structs§
- Builder
- An intermediate builder for constructing an
Error. - Error
- An error type that can carry optional state, source, context, and payload.
Traits§
- Builder
Ext - Extension trait for attaching context, state, or payload to an existing error.
- Error
Ext - Extension trait for materializing or erasing an error.
- State
Ext - Extension trait for extracting the state to a separate layer.