4 个版本

0.1018.2 2021 年 4 月 2 日
0.1015.2 2019 年 4 月 6 日
0.1015.1 2019 年 4 月 6 日
0.1015.0 2019 年 4 月 6 日

#1685Rust 模式

MIT/Apache

16KB
136

failchain

failchainfailure 库的一个小型配套 crate,旨在恢复 error_chain 的易用性。它通过以下方式实现:

  • chain_err
  • 非详尽的 ErrorErrorKind
  • bail!ensure! 的支持,带有自定义的 ErrorKind

failure 库推荐了三种不同的错误模式。这个库实现了最复杂(也是最有用)的一种,但没有所有 样板代码

它看起来像什么

// errors.rs
use failchain::{BoxedError, ChainErrorKind};
use failure::Fail;
use std::path::PathBuf;
use std::result::Result as StdResult;

pub type Error = BoxedError<ErrorKind>; // Use `UnboxedError` instead for
                                        // non-allocating, but bigger `Error`.
pub type Result<T> = StdResult<T, Error>;

#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum ErrorKind {
    #[fail(display = "Metadata I/O error {:?}.", 0)]
    MetadataIo(PathBuf),

    #[fail(display = "Corrupt metadata file: {}", 0)]
    CorruptMetadata(String),

    #[fail(display = "WAD I/O error {:?}.", 0)]
    WadIo(PathBuf),

    #[fail(display = "Corrupt WAD file: {}", 0)]
    CorruptWad(String),
}

impl ChainErrorKind for ErrorKind {
    type Error = Error;
}


// main.rs
use super::errors::{ErrorKind, Result};
use failchain::{
    bail,
    ensure,
    ResultExt, // for `chain_err`,
};
use std::fs::File;
use std::io::Read;
use std::path::Path;

fn validate_metadata(path: &Path, metadata: &str) -> Result<()> {
    // `ensure` is like `assert` (or failure's ensure), except it allows you to
    // specify the `ErrorKind`.
    ensure!(
        !metadata.is_empty(),
        ErrorKind::CorruptMetadata(format!("metadata file {:?} is empty", path))
    );

    // a special mode of `ensure` works for functions that return `ErrorKind`-s
    // and take a single string as argument:
    ensure!(
        metadata.len() > 100,
        ErrorKind::CorruptMetadata, // Any FnOnce(String) -> ErrorKind
        "metadata file {:?} is too long", // Rest of arguments are format args.
        path,
    );

    // `bail` is like `ensure`, but without the condition and always returns
    // early.
    bail!(
        ErrorKind::CorruptMetadata,
        "validation isn't actually implemented"
    );
}

fn load(wad: &Path, metadata: &Path) -> Result<()> {
    // `chain_err` stashes the original error as the `cause` of a new error.
    let wad_file = File::open(wad).chain_err(|| ErrorKind::WadIo(wad.to_owned()))?;

    let mut metadata_content = String::new();

    // `chain_inspect_err` stashes the original error as the `cause` of the new
    // error, but it first allows the callback to inspect it.
    let metadata_file = File::open(metadata)
        .and_then(|mut file| file.read_to_string(&mut metadata_content))
        .chain_inspect_err(|_io_error| ErrorKind::MetadataIo(metadata.to_owned()))?;

    validate_metadata(metadata, &metadata_content)?;

    Ok(())
}

未来计划

这个库是一个概念验证,作为 rust-doomerror_chain -> failure 迁移的一部分开发,并受到 @burntsushi 在 imdb-rename 中的错误处理解决方案的启发。

当前库的主要问题在于,failchain 必须通过 Error 类型别名作为公开依赖项泄漏。这可以通过自定义 derive 来轻松解决,该 derive 实现必要的 FromFail 实现,例如。

#[derive(ChainError)]
pub struct Error(BoxedError<ErrorKind>);


// expanding to
impl Fail for Error { /* delegate */ }
impl From<ErrorKind> for Error { /* delegate */ }

Rust 中的错误处理故事现在有点悬而未决,但在我看来,任何最终解决方案都应该包括这些部分(就像 error_chain 一样)。

版本

failurefailchain 的公共依赖项。库的版本号方案是 <failchain_major><failure_version><failchain_minor>。所以 0.1015.2 将是 failchain0.1.2 版本,依赖 failure0.1.5 版本。

依赖项

~64KB