#error-message #error #line-numbers #throw #utility #result

erreur

一个简化错误处理的库,包括追踪行号、自定义和传播错误信息

3 个版本

0.1.2 2024年3月25日
0.1.1 2024年3月13日
0.1.0 2024年3月13日

#2 in #throw

MIT/Apache

13KB
240

快速开始

阅读完这篇文章后,您将精通使用

  • Resultat<T>作为返回类型
  • assert_throw!(...)
  • throw!(...)
  • .catch()?.catch_()?
  • .ifnone()?.ifnone_()?

1. 返回 Resultat<T> 的示例

use erreur::*;

pub fn rand_even() -> Resultat<u64> {
    // ... function body here ...
    Ok(1)
}

注意:如果您正在编写自己的可失败函数,让它返回 Resultat<T>

2. assert_throw!(...) 的示例

use erreur::*;

fn rand_even(rng: &mut ThreadRng) -> Resultat<u64> {
    let n: u64 = rng.gen_range(1..=1000_0000);
    assert_throw!(
        // [required] boolean expression
        n % 2 == 0,
        // [optional] title          
        "UnluckyException",     
        // [optional] error message      
        format!("{} is not even", n)  
    );
    Ok(n)
}

注意:如果给出 正好一个 可选参数,则该参数被视为 错误信息,标题会自动设置为 "AssertionFailedException"

3. throw!(...) 的示例

fn rand_odd(rng: &mut ThreadRng) -> Resultat<u64> {
    let n: u64 = rng.gen_range(1..=1000_0000);
    if n % 2 == 1 {
        return Ok(n);
    } else {
        throw!(
            // [required] title.
            "UnluckyException",
            // [required] error message.
            format!("{} is not odd", n)
        );

        // throw!(); // Lazy variant
        // throw!("DummyException", ""); // equivalent
    }
}

4. .catch(...)?.catch_()? 的示例

4.1. 完整捕获

这在底层错误信息难以理解时非常有用。程序员负责自定义有用的错误信息。

use erreur::*;
use std::fs::File;

fn main() -> Resultat<()> {
    // `File::open` will show the following message on this path
    // -- "No such file or directory (os error 2)".
    // When you see this message in real business, 
    // --  you have no idea which file is missing.
    let path = "/impossible/path/!@#$%^&*()_+.file";

    // `catch` the `Result` returned by `open`,
    // write helpful message in `catch`.
    let _file = File::open(path).catch("CannotOpenFile", path)?;

    Ok(())
}

4.2. 惰性捕获

如果底层错误信息足够有用,则使用惰性捕获来跟踪调用堆栈并传播错误信息。

use erreur::*;
use rand::{rngs::ThreadRng, Rng};

fn main() -> Resultat<()> {
    let mut rng = rand::thread_rng();

    let even = rand_even(&mut rng).catch_()?;
    println!("{}", even);

    let odd = rand_odd(&mut rng).catch_()?;
    println!("{}", odd);

    Ok(())
}

5. .ifnone(...)?.ifnone_()? 的示例

如果一个 Option::None 使你的业务陷入困境,请调用 .ifnone(...)?.ifnone_()? 来抛出错误。

use std::collections::HashMap;

use erreur::*;
use rand::Rng;

fn main() -> Resultat<()> {
    let mut rng = rand::thread_rng();

    let zoo = init_dict();
    let dice = rng.gen_range(1..=6);

    let animal = zoo
        .get(&dice)
        .ifnone(
            "UnluckyException",
            format!("dice = {}", dice),
        )?;
    // there's also a lazy variant: `.ifnone_()?`
    println!("{}", animal);

    Ok(())
}

fn init_dict() -> HashMap<i32, String> {
    let mut dict = HashMap::new();
    dict.insert(1, "bear".to_string());
    dict.insert(3, "kangaroo".to_string());
    dict.insert(5, "cockatoo".to_string());
    dict
}

无运行时依赖