#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/expect-exit/0.5.2")]
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(msg: &str, err: impl Display) -> ! {
_die_perror(msg, err, exit_unwind);
}
#[inline]
pub fn die(msg: &str) -> ! {
_die(msg, process::exit);
}
#[inline]
pub fn die_perror(msg: &str, err: impl Display) -> ! {
_die_perror(msg, err, process::exit);
}
#[derive(Debug)]
pub struct ExpectationFailed {
message: String,
}
impl Display for ExpectationFailed {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", 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, f: 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, f: 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, f: F) -> T
where
F: FnOnce() -> String,
{
self.or_exit(f)
}
#[inline]
fn expect_or_die_(self, msg: &str) -> T {
self.or_die_(msg)
}
#[inline]
fn expect_or_die<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
self.or_die(f)
}
}
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, f: 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, f: 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, f: F) -> T
where
F: FnOnce() -> String,
{
self.or_exit_e(f)
}
#[inline]
fn expect_or_die_perror_(self, msg: &str) -> T {
self.or_die_e_(msg)
}
#[inline]
fn expect_or_die_perror<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
self.or_die_e(f)
}
}
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, f: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String;
#[inline]
fn expect_result<F>(self, f: F) -> Result<T, Box<dyn Error>>
where
F: FnOnce() -> String,
{
self.expect_result_nb(f)
.map_err(|err| -> Box<dyn Error> { Box::new(err) })
}
}
impl<T> Expected<T> for Option<T> {
#[inline]
fn or_exit<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Some(value) => value,
None => exit(&f()),
}
}
#[inline]
fn or_die<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Some(value) => value,
None => die(&f()),
}
}
}
impl<T, E> Expected<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn or_exit<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Ok(value) => value,
Err(_) => exit(&f()),
}
}
#[inline]
fn or_die<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Ok(value) => value,
Err(_) => die(&f()),
}
}
}
impl<T, E> ExpectedWithError<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn or_exit_e<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Err(err) => exit_perror(&f(), err),
Ok(value) => value,
}
}
#[inline]
fn or_die_e<F>(self, f: F) -> T
where
F: FnOnce() -> String,
{
match self {
Err(err) => die_perror(&f(), err),
Ok(value) => value,
}
}
}
impl<T> ExpectedResult<T> for Option<T> {
#[inline]
fn expect_result_nb<F>(self, f: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String,
{
self.ok_or_else(|| ExpectationFailed { message: f() })
}
}
impl<T, E> ExpectedResult<T> for Result<T, E>
where
E: Display,
{
#[inline]
fn expect_result_nb<F>(self, f: F) -> Result<T, ExpectationFailed>
where
F: FnOnce() -> String,
{
self.map_err(|err| ExpectationFailed {
message: format!("{}: {}", f(), err),
})
}
}
impl Expected<Self> for bool {
#[inline]
fn or_exit<F>(self, f: F) -> Self
where
F: FnOnce() -> String,
{
if !self {
exit(&f());
}
true
}
#[inline]
fn or_die<F>(self, f: F) -> Self
where
F: FnOnce() -> String,
{
if !self {
die(&f());
}
true
}
}
impl ExpectedResult<()> for bool {
#[inline]
fn expect_result_nb<F>(self, f: F) -> Result<(), ExpectationFailed>
where
F: FnOnce() -> String,
{
if self {
Ok(())
} else {
Err(ExpectationFailed { message: f() })
}
}
}