An open API service indexing awesome lists of open source software.

https://github.com/n3xed/embedded-error-chain

A rust library implementing easy error handling for embedded devices with very little memory overhead.
https://github.com/n3xed/embedded-error-chain

embedded error-handling no-alloc no-std rust rust-library

Last synced: about 1 year ago
JSON representation

A rust library implementing easy error handling for embedded devices with very little memory overhead.

Awesome Lists containing this project

README

          

# embedded-error-chain

[![build](https://github.com/N3xed/embedded-error-chain/workflows/CI/badge.svg)](https://github.com/N3xed/embedded-error-chain/actions)
[![crates.io](https://img.shields.io/crates/v/embedded-error-chain.svg)](https://crates.io/crates/embedded-error-chain)
[![docs](https://docs.rs/embedded-error-chain/badge.svg)](https://docs.rs/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](https://crates.io/crates/error-chain),
[anyhow](https://crates.io/crates/anyhow) and
[thiserror](https://crates.io/crates/thiserror), though it was made to work in `no_std`
**and** no `liballoc` environments with very little memory overhead.

## Example
```rust
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::() {
// try to fix it
0
}
else {
panic!("unfixable spi error");
}
}
};
}

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

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

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

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

License: MIT