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}