#error #no-alloc #error-value #embedded-devices #debugging #no-std

no-std embedded-error-chain

在无分配和无标准环境中轻松处理错误

2 个版本 (1 个稳定版本)

1.0.0 2020 年 11 月 20 日
0.1.1 2020 年 11 月 13 日
0.1.0 2020 年 11 月 12 日

嵌入式开发 中排名 1944

MIT 许可证

63KB
726 行(不包括注释)

embedded-error-chain

build crates.io docs

为嵌入式设备提供轻松的错误处理(无 liballocno_std)。

错误通过错误代码表示,并来自实现 ErrorCategory 特性的枚举(存在一个 derive 宏),用于按错误代码进行自定义调试打印等。每个错误代码可以有一个从 015(4 位)的值,并且您可以使用多达四个不同类别的不同错误代码来链接一个错误。

Error 类型封装了一个错误代码和错误链,大小仅为单个 u32。还有一个无类型的 DynError 类型,与 Error 不同,它没有当前错误代码的类型参数。其大小为 u32 + 指针 (usize),可用于将不同类别的源错误传递给调用者。

这个库受到了例如 error-chainanyhowthiserror 等库的启发,但它被制作成在 no_std liballoc 环境中工作,内存开销非常小。

示例

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(())
}

许可证:MIT

依赖项

~1.5MB
~35K SLoC