Crates.io | thistermination |
lib.rs | thistermination |
version | 1.1.0 |
source | src |
created_at | 2023-10-05 16:35:25.606153 |
updated_at | 2023-10-08 10:49:44.158718 |
description | A library crate to add the Termination trait to error enums inspired by thiserror |
homepage | |
repository | https://github.com/LennardKittner/thistermination |
max_upload_size | |
id | 994352 |
size | 53,877 |
thistermination is a library crate inspired by thiserror to add the std::process::Termination
trait to error enums.
[dependencies]
thistermination = "1.0"
Compiler support: requires rustc 1.56+
A struct or enum that implements the std::process::Termination
and std::fmt::Debug
traits can be returned by the main
function, allowing developers to print a message on program exit and set the exit code.
To add the std::process::Termination
trait to an enum, you can use one of three possible derive macros:
#[derive(Termination)]
: is intended to be used in combination with thiserror, this macro implements the traits std::process::Termination
and std::fmt::Debug
. The exit_code
defaults to libc::EXIT_FAILURE
, and the Debug message is the same as the Display message unless explicitly set using exit_code
and msg
.
use thistermination::{Termination};
use thiserror::Error;
#[derive(Error, Termination)]
pub enum RequestError {
#[error("request failed {0:?}")]
RequestFailed(#[from] reqwest::Error),
#[termination(msg("exiting wrong api key"))]
#[error("wrong api key")]
WrongAPIKey,
#[termination(exit_code(3))]
#[error("failed with status {0}")]
RequestStatusError(u16),
#[termination(exit_code(4), msg("exiting failed to load image {error:?}"))]
#[error("failed to load image {error:?}")]
ImageLoadError{#[from] error: image::ImageError},
}
fn main() -> Result<(), RequestError> {
Err(RequestError::WrongAPIKey)
}
#[derive(TerminationFull)]
: is intended to be used without thiserror, this macro implements the traits std::process::Termination
, std::fmt::Debug
, std::fmt::Display
, and std::error::Error
. The exit_code
defaults to libc::EXIT_FAILURE
, and msg
is required and used for both Display and Debug.
use thistermination::{TerminationFull};
#[derive(TerminationFull)]
pub enum RequestError {
#[termination(exit_code(1), msg("request failed {0:?}"))]
RequestFailed(#[from] reqwest::Error),
#[termination(exit_code(2), msg("wrong api key"))]
WrongAPIKey,
#[termination(exit_code(3), msg("failed with status {0}"))]
RequestStatusError(u16),
#[termination(exit_code(4), msg("failed to load image {error:?}"))]
ImageLoadError{#[from] error: image::ImageError},
}
fn main() -> Result<(), RequestError> {
Err(RequestError::WrongAPIKey)
}
#[derive(TerminationNoDebug)]
: is the most basic variant, implementing only the std::process::Termination
trait. If no exit_code
is provided, it defaults to libc::EXIT_FAILURE
. However, the std::fmt::Debug
trait is necessary for the enum to be returned by the main
function and must be implemented manually or using the Debug macro.
use thistermination::{TerminationNoDebug};
#[derive(TerminationNoDebug, Debug)]
pub enum RequestError {
#[termination(exit_code(1))]
RequestFailed(reqwest::Error),
WrongAPIKey,
#[termination(exit_code(3))]
RequestStatusError(u16),
ImageLoadError{error: image::ImageError},
}
fn main() -> Result<(), RequestError> {
Err(RequestError::WrongAPIKey)
}
thistermination does not appear in your public API; the macros simply implement the the various traits.
The macros can be derived for unit enums, enums with named fields, and enum tuples.
msg
supports accessing the fields of the enum in a format string manner
#[termination(msg("{var}"))]
⟶ write!("{}", self.var)
#[termination(msg("{0}"))]
⟶ write!("{}", self.0)
#[termination(msg("{var:?}"))]
⟶ write!("{:?}", self.var)
#[termination(msg("{0:?}"))]
⟶ write!("{:?}", self.0)
You can also specify additional format string arguments for msg
#[derive(TerminationFull)]
pub enum RequestError {
#[termination(exit_code(4), msg("failed to load image {0:?}"))]
ImageLoadError(#[from] image::ImageError),
}
Using #[from]
will generate a std::convert::From
implementation for the specific variant. A variant with #[from]
is not allowed to contain any additional fields and can only be used in combination with #[derive(TerminationFull)]
.
#[derive(TerminationFull)]
pub enum CLIError {
#[termination(exit_code(4), msg("Invalid argument {0}, expected < {}", i16::MAX))]
InvalidArgument(u16),
}
You can also change the default values of exit_code
and msg
by adding the #[termination(...)]
helper attribute to the enum itself.
#[derive(Error, Termination)]
#[termination(exit_code(3), msg("Fatal Error"))]
pub enum RequestError {
#[error("request failed {0:?}")]
RequestFailed(#[from] reqwest::Error),
#[error("wrong api key")]
WrongAPIKey,
#[error("failed with status {0}")]
RequestStatusError(u16),
#[termination(exit_code(4), msg("exiting failed to load image {error:?}"))]
#[error("failed to load image {error:?}")]
ImageLoadError{#[from] error: image::ImageError},
}
#[derive(TerminationFull)]
can be used instead of thiserror as it offers many of the basic features of thiserror. However, it lacks some features like #[source]
, #[backtrace]
, the ability to automatically detect a backtrace, and #[error(transparent)]
. If any of these features are required, you can use thiserror in combination with #[derive(Termination)]
.