Crate errs

Crate errs 

Source
Expand description

This crate is for error handling in Rust programs, providing an Err struct which represents an error with a reason.

The type of this reason is any, but typically an enum variant is used. The name of this enum variant indicates the reason for the error, and its fields store contextual information about the situation in which the error occurred. Since the path of an enum variant, including its package, is unique within a program, the enum variant representing the reason is useful for identifying the specific error, locating where it occurred, or generating appropriate error messages, etc.

Optionally, by using errs-notify feature and registering error handlers in advance, it is possible to receive notifications either synchronously or asynchronously at the time the error struct is created.

There is also an errs-notify-tokio feature, which is for applications that use the Tokio runtime. If this feature is used, error notifications are received by asynchronous handlers running on the Tokio runtime.

§Install

In Cargo.toml, write this crate as a dependency:

[dependencies]
errs = "0.7.1"

If you want to use error notification, specify errs-notify or errs-notify-tokio in the dependency features. The errs-notify feature is for general use, while the errs-notify-tokio feature is for use with the Tokio runtime.

[dependencies]
errs = { version = "0.7.1", features = ["errs-notify"] }

If you are using Tokio, you should specify errs-notify-tokio:

[dependencies]
errs = { version = "0.7.1", features = ["errs-notify-tokio"] }

§Usage

§Err instantiation and identification of a reason

The Err struct can be instantiated with new<R>(reason: R) function or with_source<R, E>(reason: R, source: E) function.

Then, the reason can be identified with reason<R>(&self) method and a match statement, or match_reason<R>(&self, func fn(&R)) method.

The following code is an example which uses new<R>(reason: R) function for instantiation, and reason<R>(&self) method and a match statement for identifying a reason:

use errs::Err;

#[derive(Debug)]
enum Reasons {
    IllegalState { state: String },
    // ...
}

let err = Err::new(Reasons::IllegalState { state: "bad state".to_string() });

match err.reason::<Reasons>() {
    Ok(r) => match r {
        Reasons::IllegalState { state } => println!("state = {state}"),
        _ => { /* ... */ }
    }
    Err(err) => match err.reason::<String>() {
        Ok(s) => println!("string reason = {s}"),
        Err(err) => { /* ... */ }
    }
}

§Macro-based Registration of Err Handlers

In addition to function-based handler registration, this crate provides macros for registering error handlers from a static context (e.g., outside a function body). These macros utilize the inventory crate to collect handlers at compile time, making them available for the error notification system.

Registered handlers are activated when the fix_err_handlers function is called or implicitly upon the first Err instance creation.

§add_sync_err_handler!

Statically registers a synchronous error handler.

#[cfg(feature = "errs-notify")]
use errs::{add_sync_err_handler, Err};
#[cfg(feature = "errs-notify")]
use chrono::{DateTime, Utc};

#[cfg(feature = "errs-notify")]
fn my_static_sync_handler(err: &Err, tm: DateTime<Utc>) {
    println!("[Static Sync] Error at {}: {}", tm, err);
}

#[cfg(feature = "errs-notify")]
add_sync_err_handler!(my_static_sync_handler);
§add_async_err_handler!

Statically registers a general-purpose asynchronous error handler.

#[cfg(feature = "errs-notify")]
use errs::{add_async_err_handler, Err};
#[cfg(feature = "errs-notify")]
use chrono::{DateTime, Utc};

#[cfg(feature = "errs-notify")]
fn my_static_async_handler(err: &Err, tm: DateTime<Utc>) {
    println!("[Static Async] Error at {}: {}", tm, err);
}

#[cfg(feature = "errs-notify")]
add_async_err_handler!(my_static_async_handler);
§add_tokio_async_err_handler!

Statically registers a Tokio-based asynchronous error handler.

#[cfg(feature = "errs-notify-tokio")]
use errs::{add_tokio_async_err_handler, Err};
#[cfg(feature = "errs-notify-tokio")]
use chrono::{DateTime, Utc};
use std::sync::Arc;

#[cfg(feature = "errs-notify-tokio")]
add_tokio_async_err_handler!(async |err: Arc<Err>, tm: DateTime<Utc>| {
    tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
    println!("[Static Tokio Async] Error at {}: {}", tm, err);
});

// You can also register a function pointer:
// #[cfg(feature = "errs-notify-tokio")]
// fn my_static_tokio_handler(err: Arc<Err>, tm: DateTime<Utc>) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
//     Box::pin(async move {
//         println!("[Static Tokio Async Fn] Error at {}: {}", tm, err);
//     })
// }
// #[cfg(feature = "errs-notify-tokio")]
// add_tokio_async_err_handler!(my_static_tokio_handler);

After registering handlers using either functions or macros, ensure you call fix_err_handlers() or allow the first error instantiation to implicitly fix the handlers.

§Notification of Err instantiations

This crate optionally provides a feature to notify pre-registered error handlers when an Err is instantiated. Multiple error handlers can be registered, and you can choose to receive notifications either synchronously or asynchronously. To register error handlers that receive notifications synchronously, use the add_sync_err_handler function.

For asynchronous notifications, there are two approaches: one for general use and another specifically for applications using the Tokio runtime.

For general-purpose asynchronous notifications, use the add_async_err_handler function. This function is available when the errs-notify feature is enabled.

For applications using the Tokio runtime, the add_tokio_async_err_handler function should be used. This function is available when the errs-notify-tokio feature is enabled and ensures that the asynchronous error handling is integrated with the Tokio runtime.

Error notifications will not occur until the fix_err_handlers function is called. This function locks the current set of error handlers, preventing further additions and enabling notification processing.

#[cfg(feature = "errs-notify")]
errs::add_sync_err_handler(|err, tm| {
    println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
});

#[cfg(feature = "errs-notify")]
errs::add_async_err_handler(|err, tm| {
    println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
});

#[cfg(feature = "errs-notify-tokio")]
errs::add_tokio_async_err_handler(async |err, tm| {
    println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
});
// When rust version is less than 1.85.0.
//errs::add_tokio_async_err_handler(|err, tm| Box::pin(async move {
//    println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
//}));

#[cfg(any(feature = "errs-notify", feature = "errs-notify-tokio"))]
errs::fix_err_handlers();

Macros§

add_async_err_handler
Statically registers an asynchronous error handler.
add_sync_err_handler
Statically registers a synchronous error handler.
add_tokio_async_err_handler
Statically registers a Tokio-based asynchronous error handler.

Structs§

Err
Struct that represents an error with a reason.
ErrHandlingErrorerrs-notify or errs-notify-tokio
Represents an error that occurred during the error handling notification process.

Enums§

ErrHandlingErrorKinderrs-notify or errs-notify-tokio
Represents the specific kind of error that can occur within the error handling notification system.

Functions§

add_async_err_handlererrs-notify
Registers an asynchronous error handler.
add_sync_err_handlererrs-notify
Registers a synchronous error handler.
add_tokio_async_err_handlererrs-notify-tokio
Registers a Tokio-based asynchronous error handler.
fix_err_handlerserrs-notify or errs-notify-tokio
Fixes the set of registered error handlers, preventing any further additions.

Type Aliases§

Result
A specialized Result type for errs crate, where the error type is Err.