1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! *There is nothing at all in your return type, useful or otherwise.*
//!
//! Proc macro attribute for a more customizable alternative to the standard library's
//! `Termination` trait.
//!
//! As a simple example, this replicates the standard behavior for `fn main()` returning
//! `Result<T, E>`:
//! ```should_panic
//! # #[derive(Debug)]
//! # enum Error {
//! #     Failed,
//! # }
//! use whaterror::whaterror;
//!
//! #[whaterror(|err| eprintln!("Error: {:#?}", err))]
//! fn main() -> Result<(), Error> {
//!     Err(Error::Failed)
//! }
//! ```
//!
//! If your handler returns, `whaterror` will automatically exit with code 1 (or panic if inside a
//! test).
//!
//! This also works for `Option<T>`:
//! ```should_panic
//! use whaterror::whaterror;
//!
//! #[whaterror(|| eprintln!("returned None"))]
//! fn main() -> Option<()> {
//!     None
//! }
//! ```
//!
//! The `||` isn't necessary in this case, since there are no arguments:
//! ```
//! use whaterror::whaterror;
//!
//! #[whaterror(unreachable!())]
//! fn main() -> Option<()> {
//!     Some(())
//! }
//! ```
//!
//! This works for non-`()` types just like you would expect. Non-`main` functions are technically
//! allowed, but currently have very strict limitations.
//! These limitations are planned to be lifted in the future.

#![warn(missing_docs)]

pub mod option;
pub mod result;
mod unit;

#[doc(transparent)]
pub use whaterror_macros::*;

/// Represents an error to be handled by `whaterror`.
pub trait FatalError<T> {
    /// Handle the error using the provided handler.
    fn handle(self, handler: T);
}

/// Represents a return value to be handled by `whaterror`.
pub trait Termination {
    /// Type for a successful result.
    type Ok;

    /// Type for an unsuccessful result. This should implement FatalError<T> for at least one type.
    type Err;

    /// Convert to a Result<T> for handling.
    fn into_result(self) -> Result<Self::Ok, Self::Err>;
}

/// USED BY MACRO, NOT PUBLIC API
#[doc(hidden)]
pub fn terminate(test: bool) -> ! {
    if test {
        panic!()
    } else {
        std::process::exit(1)
    }
}