Rust错误处理库garando_errors的使用,garando_errors提供高效且可定制的错误处理解决方案

Rust错误处理库garando_errors的使用,garando_errors提供高效且可定制的错误处理解决方案

garando_errors是Rust编译器不稳定库librustc_errors的一个稳定版本实现。它提供了高效且可定制的错误处理解决方案,能够在Rust稳定版中使用。

安装

在Cargo.toml中添加依赖:

garando_errors = "0.1.0"

或者运行:

cargo add garando_errors

示例使用

下面是一个使用garando_errors的完整示例:

use garando_errors::{emitter::Emitter, Handler};
use garando_pos::{Span, MultiSpan};
use std::path::PathBuf;

fn main() {
    // 创建错误处理程序
    let mut handler = Handler::with_tty_emitter(
        false,  // 是否颜色化输出
        false,  // 是否显示错误说明
        false,  // 是否显示错误代码
        None,   // 可选的文件名映射
    );

    // 创建一个错误位置(span)
    let span = Span::new(
        0,  // 起始位置
        10, // 结束位置
        0,  // 上下文索引
    );

    // 创建多位置错误
    let multi_span = MultiSpan::from_span(span);

    // 发出错误
    handler.err(
        "这是一个示例错误",  // 错误消息
        "E0001",          // 错误代码
        multi_span,       // 错误位置
        None,             // 可选帮助消息
        None,             // 可选错误说明
    );

    // 发出警告
    handler.warn(
        "这是一个示例警告",
        "W0001",
        multi_span,
        None,
        None,
    );

    // 发出帮助信息
    handler.help(
        "这是一个示例帮助信息",
        multi_span,
        None,
    );
}

特性

  • 提供TTY和非TTY输出支持
  • 支持颜色化输出
  • 可以添加错误代码和说明
  • 支持多位置错误标记
  • 可定制的错误格式

许可证

garando_errors采用双许可证:

  • Apache License, Version 2.0
  • MIT license

构建状态

CI (Linux) CI (macOS) CI (Windows)

完整示例demo

以下是一个更完整的示例,展示了如何使用garando_errors处理多个错误和位置:

use garando_errors::{emitter::Emitter, Handler};
use garando_pos::{Span, MultiSpan};
use std::path::PathBuf;

fn main() {
    // 创建错误处理程序,启用颜色输出
    let mut handler = Handler::with_tty_emitter(
        true,   // 启用颜色化输出
        true,   // 显示错误说明
        true,   // 显示错误代码
        None,   // 可选的文件名映射
    );

    // 创建多个错误位置
    let span1 = Span::new(0, 10, 0);  // 第一个错误位置
    let span2 = Span::new(15, 25, 0); // 第二个错误位置
    
    // 创建多位置错误
    let multi_span = MultiSpan::from_spans(vec![span1, span2]);

    // 发出带有帮助信息的错误
    handler.err(
        "变量未声明",  // 错误消息
        "E0425",      // 错误代码
        multi_span,   // 错误位置
        Some("尝试声明这个变量或检查拼写"), // 帮助消息
        Some("未声明的变量错误"),  // 错误说明
    );

    // 发出警告
    handler.warn(
        "未使用的变量",
        "W0161",
        MultiSpan::from_span(span1),
        Some("考虑删除这个未使用的变量"),
        Some("未使用变量警告"),
    );

    // 发出帮助信息
    handler.help(
        "更多帮助信息请查看文档",
        MultiSpan::from_span(span2),
        Some("https://example.com/docs"),
    );

    // 发出多个错误
    for i in 0..3 {
        let span = Span::new(i * 10, i * 10 + 5, 0);
        handler.err(
            &format!("示例错误 {}", i + 1),
            &format!("E{:04}", 1000 + i),
            MultiSpan::from_span(span),
            None,
            None,
        );
    }
}

1 回复

Rust错误处理库garando_errors使用指南

garando_errors是一个为Rust设计的高效且可定制的错误处理库,它提供了灵活的错误定义和处理机制,特别适合需要细粒度错误控制的应用程序。

主要特性

  1. 高效的错误处理机制
  2. 完全可定制的错误类型
  3. 简洁的错误定义语法
  4. 支持错误链和上下文信息
  5. 与标准库std::error::Error兼容

基本使用方法

添加依赖

首先在Cargo.toml中添加依赖:

[dependencies]
garando_errors = "0.1"

定义自定义错误

use garando_errors::{Error, ErrorKind};

// 定义错误种类
#[derive(Debug, ErrorKind)]
pub enum MyErrorKind {
    #[error("Invalid input")]
    InvalidInput,
    #[error("Network error")]
    NetworkError,
    #[error("Database error: {0}")]
    DatabaseError(String),
}

// 定义错误类型
#[derive(Debug, Error)]
#[error(kind = MyErrorKind)]
pub struct MyError {
    pub source: Option<Box<dyn std::error::Error>>,
    pub context: Vec<String>,
}

使用自定义错误

fn validate_input(input: &str) -> Result<(), MyError> {
    if input.is_empty() {
        Err(MyErrorKind::InvalidInput.into())
    } else {
        Ok(())
    }
}

fn connect_to_db() -> Result<(), MyError> {
    // 模拟数据库连接失败
    Err(MyErrorKind::DatabaseError("Connection timed out".to_string()).into())
}

fn process_data(input: &str) -> Result<(), MyError> {
    validate_input(input)?;
    connect_to_db()?;
    Ok(())
}

添加错误上下文

use garando_errors::Context;

fn complex_operation() -> Result<(), MyError> {
    let result = process_data("");
    
    result.context("Failed to process data in complex operation")?;
    Ok(())
}

错误处理示例

fn main() {
    match complex_operation() {
        Ok(_) => println!("Operation succeeded"),
        Err(e) => {
            eprintln!("Error: {}", e);
            
            // 打印完整的错误链
            if let Some(source) = e.source() {
                eprintln!("Caused by: {}", source);
            }
            
            // 打印上下文信息
            if !e.context.is_empty() {
                eprintln!("Context:");
                for ctx in &e.context {
                    eprintln!("- {}", ctx);
                }
            }
        }
    }
}

高级用法

自定义错误转换

impl From<std::io::Error> for MyError {
    fn from(err: std::io::Error) -> Self {
        MyErrorKind::NetworkError.with_source(err)
    }
}

组合多个错误

fn multi_step_operation() -> Result<(), MyError> {
    let op1 = step_one().context("Step one failed")?;
    let op2 = step_two().context("Step two failed")?;
    step_three(op1, op2).context("Step three failed")
}

条件错误构建

fn conditional_error(condition: bool) -> Result<(), MyError> {
    if condition {
        Ok(())
    } else {
        Err(MyErrorKind::InvalidInput
            .with_message("Condition was false")
            .with_context("Additional context information"))
    }
}

性能建议

  1. 对于频繁返回的错误,考虑使用&'static str而不是String来存储错误信息
  2. 使用ErrorKind的简单变体(不带附加数据)可以获得最佳性能
  3. 只有在需要时才附加上下文信息

完整示例demo

下面是一个使用garando_errors库的完整示例,展示了从错误定义到处理的完整流程:

use garando_errors::{Error, ErrorKind, Context};

// 1. 定义错误种类
#[derive(Debug, ErrorKind)]
pub enum AppErrorKind {
    #[error("Invalid input: {0}")]
    InvalidInput(String),
    #[error("IO error")]
    IoError,
    #[error("Calculation error")]
    CalcError,
}

// 2. 定义错误类型
#[derive(Debug, Error)]
#[error(kind = AppErrorKind)]
pub struct AppError {
    pub source: Option<Box<dyn std::error::Error>>,
    pub context: Vec<String>,
}

// 3. 实现从std::io::Error转换
impl From<std::io::Error> for AppError {
    fn from(err: std::io::Error) -> Self {
        AppErrorKind::IoError.with_source(err)
    }
}

// 示例函数:读取文件内容
fn read_file(path: &str) -> Result<String, AppError> {
    std::fs::read_to_string(path)
        .map_err(|e| e.into())
        .context(format!("Failed to read file: {}", path))?
}

// 示例函数:处理业务逻辑
fn process_content(content: &str) -> Result<f64, AppError> {
    if content.is_empty() {
        return Err(AppErrorKind::InvalidInput("Empty content".to_string()).into());
    }
    
    // 模拟计算
    content.parse::<f64>()
        .map_err(|_| AppErrorKind::CalcError.into())
}

// 组合操作
fn run_operations(file_path: &str) -> Result<f64, AppError> {
    let content = read_file(file_path)?;
    let result = process_content(&content)?;
    Ok(result)
}

fn main() {
    match run_operations("data.txt") {
        Ok(value) => println!("Result: {}", value),
        Err(e) => {
            eprintln!("Error occurred: {}", e);
            
            // 打印错误链
            if let Some(source) = e.source() {
                eprintln!("Caused by: {}", source);
            }
            
            // 打印上下文
            if !e.context.is_empty() {
                eprintln!("Context:");
                for ctx in &e.context {
                    eprintln!("- {}", ctx);
                }
            }
        }
    }
}

这个完整示例展示了:

  1. 自定义错误类型的定义
  2. 标准库错误的转换
  3. 错误上下文的使用
  4. 多步骤操作中的错误处理
  5. 完整的错误打印和诊断信息

你可以根据实际需求调整错误类型和业务逻辑,garando_errors提供了灵活的错误处理机制来满足各种场景的需求。

回到顶部