[][src]Crate embedded_error_chain

Easy error handling for embedded devices (no liballoc and no_std).

Errors are represented by error codes and come from enums that implement the ErrorCategory trait (a derive macro exists), which is used for custom debug printing per error code among other things. Each error code can have a value from 0 to 15 (4 bits) and you can chain an error with up to four different error codes of different categories.

The Error type encapsulates an error code and error chain, and is only a single u32 in size. There is also an untyped DynError type, which unlike Error does not have a type parameter for the current error code. Its size is a u32 + pointer (usize), which can be used to forward source errors of different categories to the caller.

This library was inspired by libraries such as error-chain, anyhow and thiserror, though it was made to work in no_std and no liballoc environments with very little memory overhead.

Example

use embedded_error_chain::prelude::*;

#[derive(Clone, Copy, ErrorCategory)]
#[repr(u8)]
enum SpiError {
    BusError,
    // ...
}

static LAST_GYRO_ACC_READOUT: usize = 200;

#[derive(Clone, Copy, ErrorCategory)]
#[error_category(links(SpiError))]
#[repr(u8)]
enum GyroAccError {
    InitFailed,

    #[error("{variant} (readout={})", LAST_GYRO_ACC_READOUT)]
    ReadoutFailed,

    /// Value must be in range [0, 256)
    #[error("{variant}: {summary}")]
    InvalidValue,
}

fn main() {
    if let Err(err) = calibrate() {
        // log the error
        println!("{:?}", err);
        // ...
    }

    let readout = match gyro_acc_readout() {
        Ok(val) => val,
        Err(err) => {
            if let Some(spi_error) = err.code_of_category::<SpiError>() {
                // try to fix it
                0
            }
            else {
                panic!("unfixable spi error");
            }
        }
    };
}

fn spi_init() -> Result<(), SpiError> {
    Err(SpiError::BusError)
}

fn gyro_acc_init() -> Result<(), Error<GyroAccError>> {
    spi_init().chain_err(GyroAccError::InitFailed)?;
    Ok(())
}

fn gyro_acc_readout() -> Result<u32, Error<GyroAccError>> {
    Err(SpiError::BusError.chain(GyroAccError::InvalidValue))
}

fn calibrate() -> Result<(), DynError> {
    gyro_acc_init()?;
    // other stuff...
    Ok(())
}

Modules

marker

Marker types.

prelude

Everything for easy error handling.

Structs

DynError

Untyped counterpart to Error.

Error

A typed error with an optional error chain of up to four source errors that represent the cause of this error.

ErrorCategoryHandle

A handle to a type that implements ErrorCategory.

ErrorCodeFormatterVal

A wrapped ErrorCodeFormatter value.

ErrorData

The entire data of the error and its error code chain.

ErrorIter

An iterator over all error codes in this Error.

Constants

ERROR_CHAIN_LEN

The maximum amount of error codes that can be chained to an Error or DynError.

Traits

ChainError

A trait that allows chaining of Error and DynError values and any value of a type that implements ErrorCategory.

ErrorCategory

A trait that implements the logic for debug printing and ErrorCode conversion. It also specifies the links to other error categories that allows errors of different categories to be chained.

ResultChainError

A trait that allows chaining if a Result contains an Error value.

Functions

format_chained

Debug format the given error_code using f if f is Some, get the ErrorCategoryHandle of the type parameter C, and get the next ErrorCodeFormatter if next_formatter is Some.

Type Definitions

ErrorCode

An error code belonging to an ErrorCategory.

ErrorCodeFormatter

A chained formatter function for a single error category.

Derive Macros

ErrorCategory

Derive ErrorCategory for an enum.