Rust错误处理库thiserror-nostd-notrait的使用,支持无标准库和无trait的轻量级错误处理

Rust错误处理库thiserror-nostd-notrait的使用,支持无标准库和无trait的轻量级错误处理

示例

use thiserror_nostd_notrait::Error;

#[derive(Error, Debug)]
pub enum DataStoreError {
    #[error("data store disconnected")]
    Disconnect(#[from] io::Error),
    #[error("the data for key `{0}` is not available")]
    Redaction(String),
    #[error("invalid header (expected {expected:?}, found {found:?})")]
    InvalidHeader {
        expected: String,
        found: String,
    },
    #[error("unknown data store error")]
    Unknown,
}

完整示例代码

// 在no_std环境下的使用示例
#![no_std]

use core::fmt;
use thiserror_nostd_notrait::Error;

#[derive(Error, Debug)]
pub enum CustomError {
    #[error("Invalid value: {0}")]
    InvalidValue(u32),
    
    #[error("Operation failed")]
    OperationFailed,
    
    #[error("Nested error: {0}")]
    NestedError(#[from] OtherError),
}

#[derive(Debug)]
pub struct OtherError;

impl fmt::Display for OtherError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Other error occurred")
    }
}

fn main() {
    let err = CustomError::InvalidValue(42);
    println!("Error: {}", err);  // 输出: Error: Invalid value: 42
    
    let nested_err = CustomError::NestedError(OtherError);
    println!("Nested error: {}", nested_err);  // 输出: Nested error: Other error occurred
}

使用说明

  1. 在Cargo.toml中添加依赖:
[dependencies]
thiserror = { version = "1.0", package = "thiserror-nostd-notrait" }
  1. 主要特点:
  • 支持no_std环境
  • 不强制要求实现Error trait
  • 可以自动生成Display实现
  • 支持从其他错误类型转换
  • 支持错误消息格式化
  1. 消息格式化支持:
  • #[error("{var}")]write!("{}", self.var)
  • #[error("{0}")]write!("{}", self.0)
  • #[error("{var:?}")]write!("{:?}", self.var)
  • #[error("{0:?}")]write!("{:?}", self.0)
  1. 编译器要求:Rust 1.56+

与标准thiserror的区别

这个fork版本在no_std环境下不自动派生Error trait,但仍然保留了其他功能如Display实现、错误转换等。适用于需要在无标准库环境中使用thiserror功能的场景。


1 回复

Rust错误处理库thiserror-nostd-notrait的使用指南

简介

thiserror-nostd-notraitthiserror的一个变体版本,专为无标准库(no_std)和无trait对象的环境设计。它提供了轻量级的错误处理能力,适用于嵌入式系统和其他资源受限的环境。

主要特性

  • 支持no_std环境
  • 不依赖trait对象
  • 轻量级实现
  • 保留thiserror的主要语法和功能

使用方法

基本安装

Cargo.toml中添加依赖:

[dependencies]
thiserror-nostd-notrait = "0.1"

基础示例

#![no_std]

use thiserror_nostd_notrait as thiserror;

#[derive(thiserror::Error, Debug)]
enum MyError {
    #[error("invalid value: {0}")]
    InvalidValue(i32),
    
    #[error("operation timed out")]
    Timeout,
    
    #[error("I/O error")]
    Io,
}

fn might_fail(value: i32) -> Result<(), MyError> {
    if value < 0 {
        Err(MyError::InvalidValue(value))
    } else {
        Ok(())
    }
}

嵌套错误处理

#[derive(thiserror::Error, Debug)]
enum ApiError {
    #[error("network error: {0}")]
    Network(#[from] NetworkError),
    
    #[error("parsing error: {0}")]
    Parse(#[from] ParseError),
}

#[derive(thiserror::Error, Debug)]
enum NetworkError {
    #[error("connection failed")]
    ConnectionFailed,
}

#[derive(thiserror::Error, Debug)]
enum ParseError {
    #[error("invalid format")]
    InvalidFormat,
}

自定义错误上下文

#[derive(thiserror::Error, Debug)]
enum CustomError {
    #[error("failed with code {code}: {message}")]
    OperationFailed {
        code: u32,
        message: &'static str,
    },
    
    #[error("configuration error in {file} at line {line}")]
    ConfigError {
        file: &'static str,
        line: u32,
    },
}

完整示例demo

下面是一个完整的嵌入式应用示例,展示了thiserror-nostd-notrait在实际项目中的使用:

#![no_std]

use thiserror_nostd_notrait as thiserror;
use core::fmt;

// 定义硬件相关错误
#[derive(thiserror::Error, Debug)]
enum HardwareError {
    #[error("sensor {id} initialization failed")]
    SensorInitFailed { id: u8 },
    
    #[error("communication timeout with device {0}")]
    DeviceTimeout(u8),
    
    #[error("invalid register value: {0}")]
    InvalidRegister(u8),
}

// 定义应用逻辑错误
#[derive(thiserror::Error, Debug)]
enum AppError {
    #[error("hardware failure: {0}")]
    Hardware(#[from] HardwareError),
    
    #[error("invalid configuration")]
    ConfigError,
    
    #[error("operation not allowed in current state")]
    InvalidState,
}

// 模拟硬件初始化函数
fn init_sensor(sensor_id: u8) -> Result<(), HardwareError> {
    if sensor_id > 5 {
        Err(HardwareError::SensorInitFailed { id: sensor_id })
    } else {
        Ok(())
    }
}

// 模拟应用逻辑函数
fn startup_sequence() -> Result<(), AppError> {
    init_sensor(3)?;  // 使用?操作符自动转换错误类型
    init_sensor(7)?;  // 这会返回错误
    
    Ok(())
}

// 实现简单的日志输出(在no_std环境中)
fn log_error(err: &impl fmt::Debug) {
    // 在实际嵌入式系统中,这里可能是串口输出或其他日志机制
    // 这里只是演示错误处理流程
}

fn main() {
    match startup_sequence() {
        Ok(_) => (),
        Err(e) => {
            log_error(&e);
            // 根据错误类型执行不同的恢复逻辑
            match e {
                AppError::Hardware(hw_err) => {
                    // 处理硬件错误
                },
                _ => {
                    // 处理其他错误
                }
            }
        }
    }
}

注意事项

  1. 由于是no_std环境,某些功能如std::error::Error trait不可用
  2. 错误消息必须是编译时常量(&'static str
  3. 相比标准thiserror,功能有所精简以保持轻量

适用场景

  • 嵌入式系统开发
  • 操作系统内核开发
  • 需要极致轻量级的应用
  • 无法或不想使用trait对象的场景

性能特点

thiserror-nostd-notrait相比标准thiserror

  • 编译后二进制更小
  • 内存占用更低
  • 不包含动态分发开销
  • 适合对资源要求严格的场景
回到顶部