Skip to main content

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}