#![deny(missing_docs)]
#![deny(clippy::missing_docs_in_private_items)]
#![doc(html_root_url = "https://docs.rs/expect-exit/0.5.3")]
#![deprecated(
note = "This module is in maintenance mode; the `anyhow` library might be a better choice"
)]
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::panic;
use std::process;
struct ExitHelper {
code: i32,
}
impl Drop for ExitHelper {
fn drop(&mut self) {
process::exit(self.code);
}
}
#[inline]
pub fn exit_unwind(code: i32) -> ! {
panic::resume_unwind(Box::new(ExitHelper { code }));
}
#[allow(clippy::print_stderr)]
fn _die(msg: &str, exit: fn(i32) -> !) -> ! {
eprintln!("{msg}");
exit(1);
}
#[allow(clippy::print_stderr)]
fn _die_perror(msg: &str, err: impl Display, exit: fn(i32) -> !) -> ! {
eprintln!("{msg}: {err}");
exit(1);
}
#[inline]
pub fn exit(msg: &str) -> ! {
_die(msg, exit_unwind);
}
#[inline]
pub fn exit_perror<E: Display>(msg: &str, err: E) -> ! {
_die_perror(msg, err, exit_unwind);
}
#[inline]
pub fn die(msg: &str) -> ! {
_die(msg, process::exit);
}
#[inline]
pub fn die_perror<E: Display>(msg: &str, err: E) -> ! {
_die_perror(msg, err, process::exit);
}
#[derive(Debug)]
pub struct ExpectationFailed {
message: String,
}
impl Display for ExpectationFailed {
#[inline]
#[allow(clippy::min_ident_chars)]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{msg}", msg = self.message)
}
}
impl Error for ExpectationFailed {}
pub trait Expected<T>
where
Self: Sized,
{
#[inline]
fn or_exit_(self, msg: &str) -> T {
self.or_exit(|| msg.to_owned())
}
fn or_exit<F>(self, msgf: F) -> T
where
F: FnOnce() -> String;
#[inline]
fn or_die_(self, msg: &str) -> T {
self.or_die(|| msg.to_owned())
}
fn or_die<F>(self, msgf: F) -> T
where
F: FnOnce() -> String;
#[inline]
fn expect_or_exit_(self, msg: &str) -> T {
self.or_exit_(msg)
}
#[inline]
fn expect_or_exit<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.or_exit(msgf)
}
#[inline]
fn expect_or_die_(self, msg: &str) -> T {
self.or_die_(msg)
}
#[inline]
fn expect_or_die<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.or_die(msgf)
}
}
pub trait ExpectedWithError<T>: Expected<T> {
#[inline]
fn or_exit_e_(self, msg: &str) -> T {
self.or_exit_e(|| msg.to_owned())
}
fn or_exit_e<F>(self, msgf: F) -> T
where
F: FnOnce() -> String;
#[inline]
fn or_die_e_(self, msg: &str) -> T {
self.or_die_e(|| msg.to_owned())
}
fn or_die_e<F>(self, msgf: F) -> T
where
F: FnOnce() -> String;
#[inline]
fn expect_or_exit_perror_(self, msg: &str) -> T {
self.or_exit_e_(msg)
}
#[inline]
fn expect_or_exit_perror<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.or_exit_e(msgf)
}
#[inline]
fn expect_or_die_perror_(self, msg: &str) -> T {
self.or_die_e_(msg)
}
#[inline]
fn expect_or_die_perror<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.or_die_e(msgf)
}
}
pub trait ExpectedResult<T>
where
Self: Sized,
{
#[inline]
fn expect_result_nb_(self, msg: &str) -> Result<T, ExpectationFailed> {
self.expect_result_nb(|| msg.to_owned())
}
#[inline]
fn expect_result_(self, msg: &str) -> Result<T, Box<dyn Error>> {
self.expect_result(|| msg.to_owned())
}
fn expect_result_nb<F>(self, msgf: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String;
#[inline]
fn expect_result<F>(self, msgf: F) -> Result<T, Box<dyn Error>>
where
F: FnOnce() -> String,
{
self.expect_result_nb(msgf)
.map_err(|err| -> Box<dyn Error> { Box::new(err) })
}
}
impl<T> Expected<T> for Option<T> {
#[inline]
fn or_exit<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.unwrap_or_else(|| exit(&msgf()))
}
#[inline]
fn or_die<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.unwrap_or_else(|| die(&msgf()))
}
}
impl<T, E> Expected<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn or_exit<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.unwrap_or_else(|_| exit(&msgf()))
}
#[inline]
fn or_die<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
self.unwrap_or_else(|_| die(&msgf()))
}
}
impl<T, E> ExpectedWithError<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn or_exit_e<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
match self {
Err(err) => exit_perror(&msgf(), err),
Ok(value) => value,
}
}
#[inline]
fn or_die_e<F>(self, msgf: F) -> T
where
F: FnOnce() -> String,
{
match self {
Err(err) => die_perror(&msgf(), err),
Ok(value) => value,
}
}
}
impl<T> ExpectedResult<T> for Option<T> {
#[inline]
fn expect_result_nb<F>(self, msgf: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String,
{
self.ok_or_else(|| ExpectationFailed { message: msgf() })
}
}
impl<T, E> ExpectedResult<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn expect_result_nb<F>(self, msgf: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String,
{
self.map_err(|err| ExpectationFailed {
message: format!("{msg}: {err}", msg = msgf()),
})
}
}
impl Expected<Self> for bool {
#[inline]
fn or_exit<F>(self, msgf: F) -> Self
where
F: FnOnce() -> String,
{
if !self {
exit(&msgf());
}
true
}
#[inline]
fn or_die<F>(self, msgf: F) -> Self
where
F: FnOnce() -> String,
{
if !self {
die(&msgf());
}
true
}
}
impl ExpectedResult<()> for bool {
#[inline]
fn expect_result_nb<F>(self, msgf: F) -> Result<(), ExpectationFailed>
where
F: FnOnce() -> String,
{
if self {
Ok(())
} else {
Err(ExpectationFailed { message: msgf() })
}
}
}