pub struct Error<C>(/* private fields */);
Expand description
A typed error with an optional error chain of up to four source errors that represent the cause of this error.
The error chain is a singly linked list of most recent to oldest source error with a
maximum length of 4. When chaining two errors with chain()
or
chain_err()
the error code of the current error is
prepended to the front of the linked list. If the linked list is already at its
maximum length before chaining, and the feature panic-on-overflow
is enabled, the
chaining operation will panic, otherwise the oldest error will be lost. After the
current error code has been prepended, the new error code will be set as the current
and the chain operation will return a new Error
typed with the ErrorCategory
of the new error code.
Chaining an Error
with a new error code is only possible if the ErrorCategory
of the new error code links to the ErrorCategory
of the current error code. This
is done using the links
argument in the error_category
attribute, if
ErrorCategory
is implemented using the derive macro.
#[derive(Clone, Copy, ErrorCategory)]
#[repr(u8)]
enum CurrentError {
Err
}
#[derive(Clone, Copy, ErrorCategory)]
#[error_category(links(CurrentError))]
// ~~~~~~~~~~~~~~~~~~~
// This allows `CurrentError` to be chained with `NewError`
#[repr(u8)]
enum NewError {
Err
}
// Chain example
fn do_chain() -> Error<NewError> {
(CurrentError::Err).chain(NewError::Err)
}
This does not compile:
#[derive(Clone, Copy, ErrorCategory)]
#[repr(u8)]
enum CurrentError {
Err
}
#[derive(Clone, Copy, ErrorCategory)]
#[repr(u8)]
enum NewError {
Err
}
// Chain example
fn do_chain() -> Error<NewError> {
(CurrentError::Err).chain(NewError::Err)
}
Unlike DynError
which does not have a type parameter, Error
’s
type parameter specifies the ErrorCategory
of the most recent error (also called
current error). This allows the size of this struct to be reduced and so the struct is
guaranteed to only be one u32
or 4 bytes in size (the same size as ErrorData
),
whereas DynError
contains an additional pointer (usize
).
Additionally because the error category of the first error is known at
compile time, this allows for the chain()
and
chain_err()
operations to be error checked at
compile time and for them to have a constant execution time O(1)
.
But a consequence of this type parameter is, that when returning an Error
from a
function that has to forward multiple errors of different error
categories, you must always chain()
or
chain_err()
them. So instead of an inner error
being directly forwarded to the caller, you must have a single error of indirection in
between.
#[derive(Clone, Copy, ErrorCategory)]
#[repr(u8)]
enum InnerError {
SomeError
}
#[derive(Clone, Copy, ErrorCategory)]
#[error_category(links(InnerError))]
#[repr(u8)]
enum OuterError {
Inner
}
fn do_something_that_may_error() -> Result<(), Error<OuterError>> {
causes_inner_error().chain_err(OuterError::Inner)?;
// other stuff that causes `OuterError`...
}
If you want to directly forward a single or multiple source errors with different
unrelated error categories and you don’t need the advantages outlined
above use DynError
instead.
Implementations§
Source§impl<C> Error<C>
impl<C> Error<C>
Sourcepub const fn new_raw(error_code: ErrorCode) -> Error<C>
pub const fn new_raw(error_code: ErrorCode) -> Error<C>
Create a new Error
with an empty chain from the supplied raw error_code
.
This function is memory-safe and will never panic, but if error_code
is not part the
ErrorCategory
C
the behavior of all method calls on the returned Error
is undefined.
Sourcepub const fn from_raw(error_data: ErrorData) -> Error<C>
pub const fn from_raw(error_data: ErrorData) -> Error<C>
Crate a new Error
from raw ErrorData
.
This function is memory-safe and will never panic, but if error_data.code()
is
not part the ErrorCategory
C
or the contained error chain is invalid, the
behavior of all method calls on the returned Error
is undefined.
Source§impl<C> Error<C>
impl<C> Error<C>
Sourcepub const fn chain_capacity(&self) -> usize
pub const fn chain_capacity(&self) -> usize
Get the capacity of the error chain.
Always returns ERROR_CHAIN_LEN
.
Source§impl<C: ErrorCategory> Error<C>
impl<C: ErrorCategory> Error<C>
Sourcepub fn new(error_code: C) -> Error<C>
pub fn new(error_code: C) -> Error<C>
Create a new Error
with an empty chain from the supplied error_code
.
Sourcepub fn caused_by<T: ErrorCategory>(&self, error_code: T) -> bool
pub fn caused_by<T: ErrorCategory>(&self, error_code: T) -> bool
Query if this error was caused by error_code
which belongs to the error category
T
.
Sourcepub fn code_of_category<T: ErrorCategory>(&self) -> Option<T>
pub fn code_of_category<T: ErrorCategory>(&self) -> Option<T>
Query the error code contained in this error that belongs to the ErrorCategory
T
. Return None
if this error was not caused by the specified error category.
Examples found in repository?
26fn main() {
27 if let Err(err) = calibrate() {
28 // log the error
29 println!("{:?}", err);
30 // ...
31 }
32
33 if let Err(err) = gyro_acc_readout_check() {
34 // log the error
35 println!("{:?}", err);
36 // ...
37 }
38
39 let _readout = match gyro_acc_readout() {
40 Ok(val) => val,
41 Err(err) => {
42 println!("{:?}", err);
43 if let Some(_spi_error) = err.code_of_category::<SpiError>() {
44 // try to fix it
45 0
46 } else {
47 panic!("unfixable spi error");
48 }
49 }
50 };
51}