#error #handler #fatal #null #stop #user #tiered

nightly no-std tiered-result

错误处理的另一种方法

1 个不稳定版本

0.1.0 2021 年 12 月 3 日

#9 in #fatal

MIT 许可证

22KB
436

分层结果

错误处理的另一种策略。

请查看 docs.rs 上的文档。


lib.rs:

此软件包为库提供错误处理的替代策略。

可能需要在错误情况下继续尝试或报告多个错误的公共函数可以接受一个额外的参数 &mut dyn ErrorHandler。当它们遇到可以部分恢复的错误时,可以调用错误处理器(该处理器会回调到库用户的代码),错误处理器将决定函数是否应该继续执行或提前停止。

当错误处理器指示提前返回时,这被视为一个致命错误,所有进一步的处理和恢复都应该停止,并且库应该尽快将控制权返回给调用者。

如果错误处理器指示继续执行,但错误不允许计算完成,则应返回 null。这导致了 TieredResult 中的四个变体:[Ok], [Err], Null, 和 Fatal

您的库代码可能如下所示

use tiered_result::TieredResult;
use std::fmt::{Display, Formatter};
pub use tiered_result::{ErrorHandler, ClientResponse};
use nullable_result::NullableResult;

pub fn public_fn(handler: &mut dyn ErrorHandler<Error, Fatality>) -> Option<i64> {
    match private_fn(handler) {
        TieredResult::Ok(n) => Some(i64::from(n)),
        TieredResult::Err(_) => Some(-1),
        TieredResult::Null => None,
        TieredResult::Fatal(_) => Some(-2)
    }
}

fn private_fn(handler: &mut dyn ErrorHandler<Error, Fatality>) -> TieredResult<u32, Error, Fatality> {//!
    let n = another_private_fn(handler)?; // <-- this `?` bubbles up the fatal error
                                          //     leaving a nullable result behind
    let n = n?; // <-- this `?` bubbles up the null/err.
    // the previous two lines could be written as let n = another_private_fn(handler)??;

    if n == 42 {
        handler.handle_error(Error("we don't like 42".to_owned()))?;
    }
    TieredResult::Ok(n + 5)
}

fn another_private_fn(handler: &mut dyn ErrorHandler<Error, Fatality>) -> TieredResult<u32, Error, Fatality> {
    // --snip--
    # TieredResult::Ok(2)
}

// a struct to represent fatal errors, can carry additional info if you need it to
struct Fatality;

#[derive(Clone, Debug)]
struct Error(String); // any old error type

impl std::error::Error for Error {}
impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
       write!(f, "There was an error: {}", self.0)
    }
}

调用应用程序可能如下所示

use the_lib_from_before::*;

#[derive(Default)]
struct Handler(u8);

impl ErrorHandler<Error, Fatality> for Handler {
    fn handle_error(&mut self, error: Error) -> ClientResponse<Fatality, ()> {
        if self.0 > 2 { // allow two errors before giving up
            ClientResponse::Throw(Fatality)
        } else {
            ClientResponse::Continue(())
        }
    }
}

let mut handler = Handler::default();
println!("{:?}", public_fn(&mut handler));

依赖项

~25KB