Expand description
§thistermination
thistermination is a library crate inspired by thiserror to add the std::process::Termination trait to error enums.
§Usage
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 traitsstd::process::Terminationandstd::fmt::Debug. Theexit_codedefaults tolibc::EXIT_FAILURE, and the Debug message is the same as the Display message unless explicitly set usingexit_codeandmsg.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 traitsstd::process::Termination,std::fmt::Debug,std::fmt::Display, andstd::error::Error. Theexit_codedefaults tolibc::EXIT_FAILURE, andmsgis 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 thestd::process::Terminationtrait. If noexit_codeis provided, it defaults tolibc::EXIT_FAILURE. However, thestd::fmt::Debugtrait is necessary for the enum to be returned by themainfunction 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) }
§Details
-
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.
-
msgsupports 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 astd::convert::Fromimplementation 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_codeandmsgby 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}, }