result_either/lib.rs
1#![doc = include_str!("../README.md")]
2#![no_std]
3use core::{
4 ops::{Deref, DerefMut},
5 option::IntoIter,
6};
7
8#[doc(hidden)]
9pub trait ResultLike: Sized {
10 type T;
11 type E;
12
13 fn by(self) -> Result<Self::T, Self::E>;
14
15 fn by_ref(&self) -> Result<&Self::T, &Self::E>;
16
17 fn by_mut(&mut self) -> Result<&mut Self::T, &mut Self::E>;
18}
19
20#[doc(hidden)]
21pub trait ThisRef<'a>: 'a {
22 type Out: ?Sized;
23
24 /// Consume self into reference
25 fn this_ref(self) -> &'a Self::Out;
26}
27
28impl<'a, T: ?Sized> ThisRef<'a> for &'a T {
29 type Out = T;
30
31 fn this_ref(self) -> &'a Self::Out {
32 self
33 }
34}
35impl<'a, T: ?Sized> ThisRef<'a> for &'a mut T {
36 type Out = T;
37
38 fn this_ref(self) -> &'a Self::Out {
39 self
40 }
41}
42
43impl<T, E> ResultLike for Result<T, E> {
44 type T = T;
45 type E = E;
46
47 #[inline]
48 fn by(self) -> Result<Self::T, Self::E> {
49 self
50 }
51
52 #[inline]
53 fn by_ref(&self) -> Result<&Self::T, &Self::E> {
54 self.as_ref()
55 }
56
57 #[inline]
58 fn by_mut(&mut self) -> Result<&mut Self::T, &mut Self::E> {
59 self.as_mut()
60 }
61}
62
63/// [`Result`] extension methods for [`Err`]
64#[allow(private_bounds, private_interfaces)]
65pub trait ResultExt: ResultLike {
66 /// Like [`Result::as_deref`], but on [`Err`]
67 ///
68 /// # Examples
69 /// ```
70 /// # use result_either::ResultExt;
71 /// let x: Result<(), String> = Err("foo".to_owned());
72 /// let y: Result<&(), &str> = x.err_as_deref();
73 /// ```
74 fn err_as_deref(&self) -> Result<&Self::T, &<Self::E as Deref>::Target>
75 where Self::E: Deref,
76 {
77 self.by_ref().map_err(Deref::deref)
78 }
79
80 /// Like [`Result::as_deref_mut`], but on [`Err`]
81 ///
82 /// # Examples
83 /// ```
84 /// # use result_either::ResultExt;
85 /// let mut x: Result<(), String> = Err("foo".to_owned());
86 /// let y: Result<&mut (), &mut str> = x.err_as_deref_mut();
87 /// ```
88 fn err_as_deref_mut(&mut self) -> Result<&mut Self::T, &mut <Self::E as Deref>::Target>
89 where Self::E: DerefMut,
90 {
91 self.by_mut().map_err(DerefMut::deref_mut)
92 }
93
94 /// Like [`Result::copied`], but on [`Err`]
95 ///
96 /// # Examples
97 /// ```
98 /// # use result_either::ResultExt;
99 /// let x: Result<(), &i32> = Err(&2);
100 /// let _: Result<(), i32> = x.copied_err();
101 /// ```
102 fn copied_err<'a>(self) -> Result<Self::T, <Self::E as ThisRef<'a>>::Out>
103 where Self::E: ThisRef<'a>,
104 <Self::E as ThisRef<'a>>::Out: Copy,
105 {
106 self.by().map_err(|e| *e.this_ref())
107 }
108
109 /// Like [`Result::cloned`], but on [`Err`]
110 ///
111 /// # Examples
112 /// ```
113 /// # use result_either::ResultExt;
114 /// let msg = "foo".to_owned();
115 /// let x: Result<(), &String> = Err(&msg);
116 /// let _: Result<(), String> = x.cloned_err();
117 /// ```
118 fn cloned_err<'a>(self) -> Result<Self::T, <Self::E as ThisRef<'a>>::Out>
119 where Self::E: ThisRef<'a>,
120 <Self::E as ThisRef<'a>>::Out: Clone,
121 {
122 self.by().map_err(|e| e.this_ref().clone())
123 }
124
125 /// Like [`Result::iter`], but on [`Err`]
126 ///
127 /// # Examples
128 /// ```
129 /// # use result_either::ResultExt;
130 /// let ok: Result<i32, i32> = Ok(1);
131 /// let err: Result<i32, i32> = Err(1);
132 ///
133 /// assert_eq!(ok.iter_err().next(), None);
134 /// assert_eq!(err.iter_err().next(), Some(&1));
135 /// ```
136 fn iter_err(&self) -> IntoIter<&Self::E> {
137 self.by_ref().err().into_iter()
138 }
139
140 /// Like [`Result::iter_mut`], but on [`Err`]
141 ///
142 /// # Examples
143 /// ```
144 /// # use result_either::ResultExt;
145 /// let mut ok: Result<i32, i32> = Ok(1);
146 /// let mut err: Result<i32, i32> = Err(1);
147 ///
148 /// assert_eq!(ok.iter_err_mut().next(), None);
149 /// assert_eq!(err.iter_err_mut().next(), Some(&mut 1));
150 /// ```
151 fn iter_err_mut(&mut self) -> IntoIter<&mut Self::E> {
152 self.by_mut().err().into_iter()
153 }
154
155 /// Like [`Result::into_iter`], but on [`Err`]
156 ///
157 /// # Examples
158 /// ```
159 /// # use result_either::ResultExt;
160 /// let ok: Result<i32, i32> = Ok(1);
161 /// let err: Result<i32, i32> = Err(1);
162 ///
163 /// assert_eq!(ok.into_iter_err().next(), None);
164 /// assert_eq!(err.into_iter_err().next(), Some(1));
165 /// ```
166 fn into_iter_err(self) -> IntoIter<Self::E> {
167 self.by().err().into_iter()
168 }
169
170 /// Like [`Result::map_or`], but on [`Err`]
171 ///
172 /// # Examples
173 /// ```
174 /// # use result_either::ResultExt;
175 /// let ok: Result<i32, &str> = Ok(1);
176 /// let err: Result<i32, &str> = Err("err");
177 ///
178 /// assert_eq!(ok.map_err_or(0, str::len), 0);
179 /// assert_eq!(err.map_err_or(0, str::len), 3);
180 /// ```
181 fn map_err_or<E, F>(self, default: E, f: F) -> E
182 where F: FnOnce(Self::E) -> E,
183 {
184 match self.by() {
185 Ok(_) => default,
186 Err(e) => f(e),
187 }
188 }
189
190 /// Like [`Result::map_or_else`], but on [`Err`]
191 ///
192 /// # Examples
193 /// ```
194 /// # use result_either::ResultExt;
195 /// let ok: Result<usize, &str> = Ok(1);
196 /// let err: Result<usize, &str> = Err("err");
197 ///
198 /// assert_eq!(ok.map_err_or_else(|n| n*2, str::len), 2);
199 /// assert_eq!(err.map_err_or_else(|n| n*2, str::len), 3);
200 /// ```
201 fn map_err_or_else<E, D, F>(self, default: D, f: F) -> E
202 where F: FnOnce(Self::E) -> E,
203 D: FnOnce(Self::T) -> E,
204 {
205 match self.by() {
206 Ok(ok) => default(ok),
207 Err(e) => f(e),
208 }
209 }
210
211 /// Like [`Result::transpose`], but on [`Err`]
212 ///
213 /// # Examples
214 /// ```
215 /// # use result_either::ResultExt;
216 /// let ok: Result<i32, Option<i32>> = Ok(1);
217 /// let none: Result<i32, Option<i32>> = Err(None);
218 /// let some: Result<i32, Option<i32>> = Err(Some(3));
219 ///
220 /// assert_eq!(ok.transpose_err(), Some(Ok(1)));
221 /// assert_eq!(none.transpose_err(), None);
222 /// assert_eq!(some.transpose_err(), Some(Err(3)));
223 /// ```
224 fn transpose_err<E>(self) -> Option<Result<Self::T, E>>
225 where Self: ResultLike<E = Option<E>>,
226 {
227 match self.by() {
228 Ok(x) => Some(Ok(x)),
229 Err(Some(e)) => Some(Err(e)),
230 Err(None) => None,
231 }
232 }
233
234 /// Like `self.map_err(Into::into)`
235 ///
236 /// # Examples
237 /// ```
238 /// # use result_either::ResultExt;
239 /// let e: Result<(), &str> = Err("foo");
240 /// let e1: Result<(), String> = e.err_into();
241 /// assert_eq!(e1, Err("foo".to_owned()));
242 /// ```
243 fn err_into<E>(self) -> Result<Self::T, E>
244 where Self::E: Into<E>,
245 {
246 self.by().map_err(Into::into)
247 }
248}
249impl<T: ResultLike> ResultExt for T { }