human_errors/option.rs
1use std::borrow::Cow;
2
3use super::*;
4
5/// Extension trait for `Option` to convert `None` values into user-friendly
6/// error types.
7///
8/// # Examples
9/// ```
10/// use human_errors::OptionExt;
11///
12/// // Converts a `None` value into a user-caused error with the provided message and advice.
13/// let value = None::<i32>.ok_or_user_err(
14/// "No value was provided.",
15/// &["Please provide a valid integer value."],
16/// );
17///
18/// // Converts a `None` value into a system-caused error with the provided message and advice.
19/// let value = None::<i32>.ok_or_system_err(
20/// "No value was provided.",
21/// &["Please check your system configuration."],
22/// );
23/// ```
24pub trait OptionExt<T> {
25 /// Converts an `Option<T>` into a `Result<T, Error>`, returning a user-caused
26 /// error with the provided message and advice if the option is `None`.
27 ///
28 /// # Examples
29 /// ```
30 /// use human_errors::OptionExt;
31 ///
32 /// let value = None::<i32>.ok_or_user_err(
33 /// "No value was provided.",
34 /// &["Please provide a valid integer value."],
35 /// );
36 /// ```
37 fn ok_or_user_err<S: Into<Cow<'static, str>>>(
38 self,
39 msg: S,
40 advice: &'static [&'static str],
41 ) -> Result<T, Error>;
42
43 /// Converts an `Option<T>` into a `Result<T, Error>`, returning a system-caused
44 /// error with the provided message and advice if the option is `None`.
45 ///
46 /// # Examples
47 /// ```
48 /// use human_errors::OptionExt;
49 ///
50 /// let value = None::<i32>.ok_or_system_err(
51 /// "No value was provided.",
52 /// &["Please check your system configuration."],
53 /// );
54 /// ```
55 fn ok_or_system_err<S: Into<Cow<'static, str>>>(
56 self,
57 msg: S,
58 advice: &'static [&'static str],
59 ) -> Result<T, Error>;
60}
61
62impl<T> OptionExt<T> for Option<T> {
63 fn ok_or_user_err<S: Into<Cow<'static, str>>>(
64 self,
65 msg: S,
66 advice: &'static [&'static str],
67 ) -> Result<T, Error> {
68 match self {
69 Some(value) => Ok(value),
70 None => Err(user(msg.into(), advice)),
71 }
72 }
73
74 fn ok_or_system_err<S: Into<Cow<'static, str>>>(
75 self,
76 msg: S,
77 advice: &'static [&'static str],
78 ) -> Result<T, Error> {
79 match self {
80 Some(value) => Ok(value),
81 None => Err(system(msg.into(), advice)),
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_ok_or_user_err_some() {
92 let value = Some(42)
93 .ok_or_user_err("No value", &["Provide a value"])
94 .unwrap();
95 assert_eq!(value, 42);
96 }
97
98 #[test]
99 fn test_ok_or_user_err_none() {
100 let err = None::<i32>
101 .ok_or_user_err("No value", &["Provide a value"])
102 .unwrap_err();
103 assert!(err.is(Kind::User));
104 assert_eq!(err.description(), "No value");
105 }
106
107 #[test]
108 fn test_ok_or_system_err_some() {
109 let value = Some(42)
110 .ok_or_system_err("No value", &["Check system"])
111 .unwrap();
112 assert_eq!(value, 42);
113 }
114
115 #[test]
116 fn test_ok_or_system_err_none() {
117 let err = None::<i32>
118 .ok_or_system_err("No value", &["Check system"])
119 .unwrap_err();
120 assert!(err.is(Kind::System));
121 assert_eq!(err.description(), "No value");
122 }
123}