#error #macro #failure

no-std custom_error

使用 custom_error! 宏定义自定义错误,无需编写大量样板代码

17 个稳定版本

1.9.2 2021 年 4 月 11 日
1.9.1 2021 年 4 月 8 日
1.8.0 2020 年 9 月 15 日
1.7.1 2019 年 7 月 30 日
1.3.0 2018 年 11 月 18 日

#308 in Rust 模式

Download history 2457/week @ 2024-04-23 2470/week @ 2024-04-30 2657/week @ 2024-05-07 2680/week @ 2024-05-14 2370/week @ 2024-05-21 2925/week @ 2024-05-28 2472/week @ 2024-06-04 2265/week @ 2024-06-11 2227/week @ 2024-06-18 2476/week @ 2024-06-25 2103/week @ 2024-07-02 2139/week @ 2024-07-09 2224/week @ 2024-07-16 2363/week @ 2024-07-23 2800/week @ 2024-07-30 2702/week @ 2024-08-06

10,486 每月下载次数
90 个 crate (69 个直接使用) 中使用

BSD-2-Clause 协议

41KB
761

Rust 自定义错误

Rust Crates.io docs.rs

这个包包含一个宏,可以让你更容易地定义自定义错误,而无需编写大量样板代码。

这个包中包含的 custom_error! 宏接受一个类型名和一系列可能的错误,并为所有情况生成一个 Rust 枚举,同时生成实现 std::error::Errorstd::fmt::Display 的所需 impl 块。

如果你只有一个错误情况,你也可以生成一个结构体而不是枚举。

现在你可以这样写

extern crate custom_error;
use custom_error::custom_error;

// Note the use of braces rather than parentheses.
custom_error!{MyError
    Unknown{code:u8} = "unknown error with code {code}.",
    Err41            = "Sit by a lake"
}

而不是

#[derive(Debug)]
enum MyError {
    Unknown { code: u8 },
    Err41,
}

impl std::error::Error for MyError {}

impl std::fmt::Display for MyError {
    fn fmt(&self, f: &mut std::fmt::Formatter)
    -> std::fmt::Result {
        match self {
            MyError::Unknown { code } => write!(f, "unknown error with code {}." , code),
            MyError::Err41 => write!(f, "Sit by a lake")
        }
    }
}

如果你只有一个错误情况,你也可以生成一个结构体

extern crate custom_error;
use custom_error::custom_error;

custom_error!{MyError{code:u8} = "error with code {code}."}

简单错误

要定义简单错误,你只需要指出以下三件事

  • 你自定义错误类型的名称,
  • 不同错误情况的名称,
  • 每个情况的文本描述。
extern crate custom_error;
use custom_error::custom_error;

custom_error!{MyError
    Bad      = "Something bad happened",
    Terrible = "This is a very serious error!!!"
}

带参数的自定义错误

你可以在错误中存储数据。为了做到这一点,请在错误类型后面的大括号内指定要存储的字段的名称和类型。

extern crate custom_error;
use custom_error::custom_error;

custom_error!{SantaError
    BadChild{name:String, foolishness:u8} = "{name} has been bad {foolishness} times this year",
    TooFar                                = "The location you indicated is too far from the north pole",
    InvalidReindeer{legs:u8}              = "The reindeer has {legs} legs"
}

assert_eq!(
    "Thomas has been bad 108 times this year",
    SantaError::BadChild{name: "Thomas".into(), foolishness: 108}.to_string());

错误消息可以使用大括号({parameter_name})引用你的参数。如果你需要一些自定义逻辑来显示你的参数,你可以使用 高级自定义错误消息

包装其他错误类型

如果你的错误原因是另一个较低级别的错误,你可以在你的一个错误情况中添加一个特殊的 source 字段来表示这一点。

因此,你可以让你的自定义错误包装其他错误类型,并且从这些外部错误类型到自定义错误类型的转换将自动实现。

#[macro_use] extern crate custom_error;
use std::{io, io::Read, fs::File, result::Result, num::ParseIntError};

custom_error! {FileParseError
    Io{source: io::Error}         = "unable to read from the file",
    Format{source: ParseIntError} = "the file does not contain a valid integer",
    TooLarge{value:u8}            = "the number in the file ({value}) is too large"
}

fn parse_hex_file(filename: &str) -> Result<u8, FileParseError> {
    let mut contents = String::new();
    // The '?' notation can convert from generic errors to our custom error type
    File::open(filename)?.read_to_string(&mut contents)?;
    let value = u8::from_str_radix(&contents, 16)?;
    if value > 42 {
        Err(FileParseError::TooLarge { value })
    } else {
        Ok(value)
    }
}

fn main() {
    let parse_result = parse_hex_file("/i'm not a file/");
    assert_eq!("unable to read from the file", parse_result.unwrap_err().to_string());
}

可见性

你可以在声明开头添加 pub 关键字来使错误类型公开。

custom_error!{pub MyError A="error a", B="error b"}

属性

您可以通过在宏调用开头添加属性来为错误类型推导属性。

custom_error!{#[derive(PartialEq,PartialOrd)] MyError A="error a", B="error b"}
assert!(MyError::A < MyError::B);

由于文档注释只是对#[doc = "..."]的语法糖,因此您也可以使用它们。

custom_error!{
   /// This is the documentation for my error type
   pub MyError A="error a", B="error b"
}

高级自定义错误消息

如果您想使用无法用简单格式化字符串表达的错误消息,您可以使用自定义代码生成错误消息。

在以下示例中,我们使用此功能根据底层IO错误的起因显示不同的错误消息。

custom_error!{ pub MyError
    Io{source: Error} = @{
        match source.kind() {
            NotFound => "The file does not exist",
            TimedOut => "The operation timed out",
            _ => "unknown error",
        }
    },
    Unknown = "unknown error"
}

nostd

此crate支持no-std:它可以在不使用rust标准库的情况下构建。要使用no-std版本,请在您的Cargo.toml中禁用此crate的std功能。

[dependencies]
custom_error = { version = "1", default-features = false } # nostd compatible

unstable

还有一个名为unstable的功能,它在no-std中实现了对AllocErrorTryReserveError的nostd错误特质的实现。

最低支持的Rust版本

此crate与Rust >= 1.36兼容并经过测试

无运行时依赖

特性