# 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.
```rust
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.