Rust错误处理库thiserror-nostd-notrait-impl的使用,支持no_std环境下的自定义错误类型

Rust错误处理库thiserror-nostd-notrait-impl的使用,支持no_std环境下的自定义错误类型

安装

在项目目录中运行以下Cargo命令:

cargo add thiserror-nostd-notrait-impl

或者在Cargo.toml中添加以下行:

thiserror-nostd-notrait-impl = "1.0.57"

基本用法

thiserror-nostd-notrait-impl是一个支持no_std环境的Rust错误处理库,它允许你在不使用标准库的情况下定义自定义错误类型。它是thiserror库的no_std兼容版本。

完整示例

以下是一个在no_std环境下使用thiserror-nostd-notrait-impl定义自定义错误类型的完整示例:

#![no_std]

use core::fmt;

// 导入thiserror-nostd-notrait-impl宏
use thiserror_nostd_notrait_impl::Error;

// 定义我们的自定义错误类型
#[derive(Debug, Error)]
pub enum MyError {
    #[error("I/O error occurred")]
    IoError,
    #[error("Parse error: {0}")]
    ParseError(&'static str),
    #[error("Invalid value: {value}")]
    InvalidValue {
        value: i32,
    },
}

// 示例使用
fn validate_input(value: i32) -> Result<(), MyError> {
    if value < 0 {
        Err(MyError::InvalidValue { value })
    } else if value > 100 {
        Err(MyError::ParseError("Value exceeds maximum limit"))
    } else {
        Ok(())
    }
}

// 测试
#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_validate_input() {
        assert!(validate_input(50).is_ok());
        assert!(matches!(validate_input(-1), Err(MyError::InvalidValue { value: -1 })));
        assert!(matches!(validate_input(101), Err(MyError::ParseError(_))));
    }
}

关键点说明

  1. #![no_std] 属性表示我们不在标准库环境下运行
  2. use thiserror_nostd_notrait_impl::Error 导入必要的宏
  3. #[derive(Debug, Error)] 自动为我们的枚举实现Error trait
  4. #[error("...")] 属性用于定义错误信息的格式

注意事项

  • 该库特别适合嵌入式开发和其他no_std环境
  • 它提供了与标准thiserror库相似的API,但去除了对标准库的依赖
  • 错误消息仍然可以使用格式化语法来包含上下文信息

项目信息

  • 许可证: MIT OR Apache-2.0
  • 版本: 1.0.57

1 回复

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

简介

thiserror-nostd-notrait-impl是一个专为no_std环境设计的Rust错误处理库,它允许你在不使用标准库的情况下创建自定义错误类型。这个库是thiserrorno_std兼容版本,但移除了对std::error::Error trait的实现。

主要特性

  • 支持no_std环境
  • 提供类似thiserror的宏语法
  • 不自动实现std::error::Error trait
  • 轻量级,适合嵌入式等受限环境

使用方法

添加依赖

首先在Cargo.toml中添加依赖:

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

基本示例

#![no_std]

use thiserror_nostd_notrait_impl::Error;

#[derive(Debug, Error)]
pub enum MyError {
    #[error("I/O error occurred")]
    IoError,
    #[error("Invalid data: {0}")]
    InvalidData(&'static str),
    #[error("Value out of range: {0}")]
    OutOfRange(i32),
}

fn might_fail(value: i32) -> Result<(), MyError> {
    if value < 0 {
        return Err(MyError::OutOfRange(value));
    }
    if value > 100 {
        return Err(MyError::InvalidData("value too large"));
    }
    Ok(())
}

使用说明

  1. 定义错误枚举: 使用#[derive(Error)]宏来自动实现错误类型的基本功能。

  2. 错误消息: 使用#[error("...")]属性为每个变体指定错误消息,支持格式化字符串。

  3. 错误转换: 虽然不实现std::error::Error,但仍支持错误转换:

#[derive(Debug, Error)]
pub enum WrapperError {
    #[error("inner error: {0}")]
    Inner(MyError),
    #[error("other error")]
    Other,
}

完整嵌入式示例

#![no_std]
#![no_main]

use cortex_m_rt::entry;
use thiserror_nostd_notrait_impl::Error;
use panic_halt as _;

#[derive(Debug, Error)]
enum SensorError {
    #[error("Sensor not responding")]
    NotResponding,
    #[error("Invalid reading: {0}")]
    InvalidReading(u16),
}

fn read_sensor() -> Result<u16, SensorError> {
    // 模拟传感器读取
    let value = 0xFFFF;
    if value == 0xFFFF {
        Err(SensorError::NotResponding)
    } else if value > 0x7FFF {
        Err(SensorError::InvalidReading(value))
    } else {
        Ok(value)
    }
}

#[entry]
fn main() -> ! {
    match read_sensor() {
        Ok(value) => {
            // 处理有效读数
        }
        Err(e) => {
            // 处理错误
            // 可以使用format_args!或其他方式记录错误
        }
    }
    
    loop {}
}

完整示例DEMO

下面是一个完整的嵌入式系统错误处理示例,展示了如何使用thiserror-nostd-notrait-impl库:

#![no_std]
#![no_main]

use core::fmt::Write;
use cortex_m_rt::entry;
use cortex_m_semihosting::hio;
use thiserror_nostd_notrait_impl::Error;
use panic_halt as _;

// 定义自定义错误类型
#[derive(Debug, Error)]
pub enum SystemError {
    #[error("传感器错误: {0}")]
    Sensor(#[from] SensorError),
    #[error("通信错误: {0}")]
    Communication(#[from] ComError),
    #[error("内存不足")]
    OutOfMemory,
}

#[derive(Debug, Error)]
pub enum SensorError {
    #[error("传感器未响应")]
    NotResponding,
    #[error("无效读数: {0}")]
    InvalidReading(u16),
}

#[derive(Debug, Error)]
pub enum ComError {
    #[error("校验和错误")]
    ChecksumError,
    #[error("超时")]
    Timeout,
}

// 模拟传感器读取函数
fn read_sensor() -> Result<u16, SensorError> {
    // 这里应该是实际的传感器读取逻辑
    let value = 0xFFFF; // 模拟无效值
    
    if value == 0xFFFF {
        Err(SensorError::NotResponding)
    } else if value > 0x7FFF {
        Err(SensorError::InvalidReading(value))
    } else {
        Ok(value)
    }
}

// 模拟通信函数
fn send_data(data: u16) -> Result<(), ComError> {
    // 这里应该是实际的通信逻辑
    if data > 1000 {
        Err(ComError::ChecksumError)
    } else {
        Ok(())
    }
}

fn system_operation() -> Result<(), SystemError> {
    let reading = read_sensor()?; // 使用?操作符自动转换错误
    
    // 处理读数
    let processed = reading * 2;
    
    // 发送数据
    send_data(processed)?;
    
    Ok(())
}

#[entry]
fn main() -> ! {
    // 创建标准输出句柄
    let mut stdout = hio::hstdout().unwrap();
    
    match system_operation() {
        Ok(_) => {
            writeln!(stdout, "系统操作成功").unwrap();
        }
        Err(e) => {
            // 记录错误
            writeln!(stdout, "错误发生: {}", e).unwrap();
            
            // 根据具体错误类型处理
            match e {
                SystemError::Sensor(sensor_err) => {
                    writeln!(stdout, "传感器错误详情: {:?}", sensor_err).unwrap();
                }
                SystemError::Communication(com_err) => {
                    writeln!(stdout, "通信错误详情: {:?}", com_err).unwrap();
                }
                SystemError::OutOfMemory => {
                    writeln!(stdout, "内存不足,需要重启").unwrap();
                }
            }
        }
    }
    
    loop {}
}

注意事项

  1. 由于不实现std::error::Error trait,这个库更适合嵌入式或完全不需要标准库的场景。

  2. 错误处理需要手动实现,没有标准库提供的自动错误转换等功能。

  3. no_std环境中,你可能需要自己实现错误报告和日志记录机制。

  4. 如果你需要与标准库交互,可能需要手动实现std::error::Error trait。

这个库为no_std环境提供了一个轻量级但功能强大的错误处理解决方案,特别适合资源受限的嵌入式系统开发。

回到顶部