giveup/
giveup.rs

1use crate::hint::HintedError;
2use colored::Colorize;
3
4/// User-geared program termination.
5pub trait Giveup<T, E>
6where
7	E: std::fmt::Display + Send + Sync,
8{
9	/// Terminate the program gracefully and display a user-geared
10	/// error message.
11	/// # Example
12	/// ```rust
13	/// use std::io;
14	/// use giveup::Giveup;
15	/// fn main() {
16	/// 	let mut input = String::new();
17	/// 	io::stdin().read_line(&mut input)
18	/// 	// Instead of panicing a user-geared error message is displayed
19	/// 		.giveup("Failed to read input");
20	/// }
21	/// ```
22	fn giveup(self, msg: &str) -> T;
23	/// Add hints to errors to help users solve the issue which
24	/// raised the error.
25	///
26	/// [`example`](crate::hint::Example::example) can be called on
27	/// `Result`s returned by this method to subsidize the hint with
28	/// an example of the recommended action.
29	fn hint(self, hint: &str) -> Result<T, HintedError<E>>;
30}
31
32impl<T, E> Giveup<T, E> for Result<T, E>
33where
34	E: std::fmt::Display + Send + Sync,
35{
36	fn giveup(self, msg: &str) -> T {
37		match self {
38			Ok(t) => t,
39			Err(e) => exit_gracefully(msg, &e),
40		}
41	}
42
43	fn hint(self, hint: &str) -> Result<T, HintedError<E>> {
44		match self {
45			Ok(t) => Ok(t),
46			Err(e) => Err(HintedError::from_hint(e, hint)),
47		}
48	}
49}
50
51fn exit_gracefully(
52	msg: &str,
53	error: &(dyn std::fmt::Display + Send + Sync)
54) -> ! {
55	eprintln!("{}: {}", msg.bold(), error);
56	std::process::exit(1);
57}