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(_))));
}
}
关键点说明
#![no_std]
属性表示我们不在标准库环境下运行use thiserror_nostd_notrait_impl::Error
导入必要的宏#[derive(Debug, Error)]
自动为我们的枚举实现Error trait#[error("...")]
属性用于定义错误信息的格式
注意事项
- 该库特别适合嵌入式开发和其他no_std环境
- 它提供了与标准
thiserror
库相似的API,但去除了对标准库的依赖 - 错误消息仍然可以使用格式化语法来包含上下文信息
项目信息
- 许可证: MIT OR Apache-2.0
- 版本: 1.0.57
Rust错误处理库thiserror-nostd-notrait-impl
使用指南
简介
thiserror-nostd-notrait-impl
是一个专为no_std
环境设计的Rust错误处理库,它允许你在不使用标准库的情况下创建自定义错误类型。这个库是thiserror
的no_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(())
}
使用说明
-
定义错误枚举: 使用
#[derive(Error)]
宏来自动实现错误类型的基本功能。 -
错误消息: 使用
#[error("...")]
属性为每个变体指定错误消息,支持格式化字符串。 -
错误转换: 虽然不实现
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 {}
}
注意事项
-
由于不实现
std::error::Error
trait,这个库更适合嵌入式或完全不需要标准库的场景。 -
错误处理需要手动实现,没有标准库提供的自动错误转换等功能。
-
在
no_std
环境中,你可能需要自己实现错误报告和日志记录机制。 -
如果你需要与标准库交互,可能需要手动实现
std::error::Error
trait。
这个库为no_std
环境提供了一个轻量级但功能强大的错误处理解决方案,特别适合资源受限的嵌入式系统开发。