#error #error-context #utilities #enhance #readability #strategies #boilerplate

easy_errors

A crate to simplify and enhance error handling in Rust

2 releases

0.1.1 Oct 23, 2024
0.1.0 Oct 23, 2024

#1032 in Rust patterns

MIT/Apache

10KB

easy_errors

easy_errors is a Rust crate that provides macros and utilities to simplify and enhance error handling. It reduces boilerplate, improves readability, and maintains Rust's safety guarantees.

FAQ

Why use easy_errors over existing error handling crates?

easy_errors offers a streamlined approach to error handling by combining powerful macros with minimal boilerplate, enhancing readability and maintainability.

Can I use easy_errors with other error handling strategies?

Absolutely! easy_errors is designed to integrate seamlessly with popular crates like thiserror and anyhow, providing flexibility to fit various project needs.

Features

  • Enhanced ? Operator: Propagate errors with additional context effortlessly.
  • Custom Error Definitions: Define custom error types with minimal boilerplate.
  • Integration with Popular Crates: Seamlessly integrates with thiserror and anyhow.

Usage

Basic example

use easy_error::{define_error, try_easy, EasyError};

define_error!(MyError, IoError, ParseError);

fn read_file() -> Result<String, EasyError> { let content = try_easy!(std::fs::read_to_string("path/to/file.txt"), "Failed to read file"); Ok(content) }

fn main() -> Result<(), EasyError> { let file_content = read_file()?; println!("File Content: {}", file_content); Ok(()) }

Using with thiserror

Integrate easy_error with thiserror for more detailed and customized error handling.

use easy_errors::{define_error, try_easy, EasyError};
use thiserror::Error;

define_error!(MyError, IoError, ParseError);

#[derive(Error, Debug)]
pub enum AppError {
    #[error("IO Error: {0}")]
    Io(#[from] MyError),

    #[error("Parse Error: {0}")]
    Parse(#[from] MyError),

    #[error("Unknown error")]
    Unknown,
}

fn read_and_parse() -> Result<(), AppError> {
    let content = try_easy!(std::fs::read_to_string("path/to/file.txt"), "Failed to read file");
    // Simulate parsing
    if content.is_empty() {
        return Err(AppError::Parse(MyError::ParseError));
    }
    Ok(())
}

fn main() -> Result<(), AppError> {
    read_and_parse()?;
    println!("File read and parsed successfully.");
    Ok(())
}


### Using with anyhow

Leverage easy_error alongside anyhow for flexible error handling without the need for defining custom error types.

```rust
use easy_errors::{try_easy, EasyError};
use anyhow::{Context, Result};

fn read_file() -> Result<String, EasyError> {
    let content = try_easy!(std::fs::read_to_string("path/to/file.txt"), "Failed to read file");
    Ok(content)
}

fn main() -> Result<()> {
    let content = read_file()
        .context("Unable to complete the read_file operation")?;
    println!("File Content: {}", content);
    Ok(())
}




### Defining Custom Errors

Use the `define_error!` macro to create custom error types.

```rust
use easy_errors::{define_error, EasyError};

define_error!(MyError, IoError, ParseError);

fn perform_task() -> Result<(), EasyError> {
    // Your code here
    Ok(())
}


### Changelog

```markdown
# Changelog

## [0.2.0] - 2024-10-22
### Added
- Enhanced `define_error!` macro with input validation.
- Integration examples with `thiserror` and `anyhow`.

### Fixed
- Resolved cyclic dependency issues within the workspace.
- Improved error messages for compile-fail tests.

## [0.1.0] - 2024-09-15
- Initial release with basic `define_error!` and `try_easy!` macros.

Dependencies

~1.5MB
~40K SLoC