rs_std_ext/
option.rs

1//! Extension for [`std::option::Option`].
2
3/// Extension methods for [`std::option::Option`].
4pub trait OptionExt<T> {
5    /// Converts an `Option` to a `Result`.
6    /// 
7    /// Unlike the standard library,
8    /// the value of `Option` is treated as `Result::Err` instead of `Result::Ok`.
9    /// 
10    /// Arguments passed to `err_or` are eagerly evaluated;
11    /// if you are passing the result of a function call,
12    /// it is recommended to use [`OptionExt::err_or_else`], which is lazily evaluated.
13    /// 
14    /// ## Example
15    /// 
16    /// ```rust
17    /// use rs_std_ext::option::OptionExt;
18    /// 
19    /// assert_eq!(Some("err").err_or(0), Err("err"));
20    /// assert_eq!(None::<&str>.err_or(0), Ok(0));
21    /// ```
22    fn err_or<U>(self, ok: U) -> Result<U, T>;
23
24    /// Converts an `Option` to a `Result`.
25    /// 
26    /// Unlike the standard library,
27    /// the value of `Option` is treated as `Result::Err` instead of `Result::Ok`.
28    /// 
29    /// ## Example
30    /// 
31    /// ```rust
32    /// use rs_std_ext::option::OptionExt;
33    /// 
34    /// assert_eq!(Some("err").err_or_else(|| 0), Err("err"));
35    /// assert_eq!(None::<&str>.err_or_else(|| 0), Ok(0));
36    /// ```
37    fn err_or_else<U>(self, f: impl FnOnce() -> U) -> Result<U, T>;
38
39
40    /// Converts an `Option` to a `Result`.
41    /// 
42    /// Unlike the standard library,
43    /// the value of `Option` is treated as `Result::Err` instead of `Result::Ok`.
44    /// 
45    /// ## Example
46    /// 
47    /// ```rust
48    /// use rs_std_ext::option::OptionExt;
49    /// 
50    /// assert_eq!(Some("err").err_or_default::<usize>(), Err("err"));
51    /// assert_eq!(None::<&str>.err_or_default::<usize>(), Ok(0));
52    /// ```
53    fn err_or_default<U: Default>(self) -> Result<U, T>;
54
55    /// Returns `true` if the `Option` is a `None` or the value inside of it matches a predicate.
56    /// 
57    /// This is equivalent to `option.is_some_and(!f)`.
58    /// 
59    /// ## Example
60    /// 
61    /// ```rust
62    /// use rs_std_ext::option::OptionExt;
63    /// 
64    /// assert_eq!(None::<usize>.is_none_or(|&i| i == 2), true);
65    /// assert_eq!(Some(5).is_none_or(|&i| i == 2), false);
66    /// ```
67    #[deprecated = "Use `Option::is_none_or` (offered by std) instead."]
68    fn is_none_or(&self, f: impl FnOnce(&T) -> bool) -> bool;
69
70    /// Returns nothing, consuming the value contained.
71    ///
72    /// ## Panics
73    /// 
74    /// Panics if the value is a `Some` with a custom panic message provided by `msg`.
75    /// 
76    /// ## Example
77    /// 
78    /// ```rust,should_panic
79    /// use rs_std_ext::option::OptionExt;
80    /// 
81    /// let x: Option<&str> = Some("10");
82    /// x.expect_none("fruits are healthy");// panics with `fruits are healthy`
83    /// ```
84    /// 
85    /// ## Recommended Message Style
86    /// 
87    /// See the documentation for [`Option::expect`][option_expect] for more information.
88    /// 
89    /// [option_expect]: std::option::Option#method.expect
90    fn expect_none(self, msg: &str);
91
92    /// Tap into an `Option` and modify its value.
93    /// 
94    /// This method captures the `Option` in order not to break the caller-chain.
95    /// 
96    /// ## Example
97    /// 
98    /// ```rust
99    /// use rs_std_ext::option::OptionExt;
100    /// 
101    /// let mut x: Option<String> = Some("4".into());
102    /// assert_eq!(x.tap_mut(|s| s.push('2')), Some("42".into()));
103    /// ```
104    fn tap_mut(self, f: impl FnOnce(&mut T)) -> Option<T>;
105}
106
107impl<T> OptionExt<T> for Option<T> {
108    fn err_or<U>(self, ok: U) -> Result<U, T> {
109        match self {
110            Some(t) => Err(t),
111            None => Ok(ok),
112        }
113    }
114
115    fn err_or_else<U>(self, f: impl FnOnce() -> U) -> Result<U, T> {
116        match self {
117            Some(t) => Err(t),
118            None => Ok(f()),
119        }
120    }
121
122    fn err_or_default<U: Default>(self) -> Result<U, T> {
123        match self {
124            Some(t) => Err(t),
125            None => Ok(U::default()),
126        }
127    }
128
129    fn is_none_or(&self, f: impl FnOnce(&T) -> bool) -> bool {
130        match self {
131            Some(t) => f(t),
132            None => true,
133        }
134    }
135
136    fn expect_none(self, msg: &str) {
137        if self.is_some() {
138            panic!("{}", msg)
139        }
140    }
141
142    fn tap_mut(mut self, f: impl FnOnce(&mut T)) -> Option<T> {
143        if let Some(val) = &mut self {
144            f(val)
145        }
146
147        self
148    }
149}