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}