1#![feature(try_trait_v2)]
2#![cfg_attr(not(any(test, feature = "std")), no_std)]
3
4use core::{convert::Infallible, fmt, iter, ops};
5
6pub use core::result::Result::{self as StdResult, Err as StdErr, Ok as StdOk};
7
8mod sealed {
9 use super::StdResult;
10
11 pub trait StdResultExt {
12 type Ok;
13 type Err;
14 }
15
16 impl<O, E> StdResultExt for StdResult<O, E> {
17 type Ok = O;
18 type Err = E;
19 }
20}
21
22pub trait StdResultExt: Into<StdResult<Self::Ok, Self::Err>> + sealed::StdResultExt {
23 fn rich(
24 self,
25 ) -> Result<
26 <Self::Ok as sealed::StdResultExt>::Ok,
27 <Self::Ok as sealed::StdResultExt>::Err,
28 Self::Err,
29 >
30 where
31 Self::Ok: StdResultExt,
32 {
33 Result::from_std(self.into().map(Into::into))
34 }
35
36 fn ok_or_recoverable<FE>(self) -> Result<Self::Ok, Self::Err, FE> {
37 Result::ok_or_recoverable(self.into())
38 }
39
40 fn ok_or_fatal<RE>(self) -> Result<Self::Ok, RE, Self::Err> {
41 Result::ok_or_fatal(self.into())
42 }
43
44 fn recoverable_or_fatal<T>(self) -> Result<T, Self::Ok, Self::Err> {
45 Result::from_err(self.into())
46 }
47
48 fn local(self) -> LocalResult<Self::Ok, Self::Err> {
49 LocalResult::from_std(self.into())
50 }
51}
52
53impl<O, E> StdResultExt for StdResult<O, E> { }
54
55#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
56pub struct CollectedErrs<C>(pub C);
57
58impl<T, E, C, EC> FromIterator<StdResult<T, E>> for CollectedErrs<StdResult<C, EC>>
59where
60 C: FromIterator<T>,
61 EC: FromIterator<E>,
62{
63 fn from_iter<I: IntoIterator<Item = StdResult<T, E>>>(iter: I) -> Self {
64 let mut iter = iter.into_iter();
65 let first_err = match (&mut iter).collect() {
66 StdOk(all_ok) => return CollectedErrs(StdOk(all_ok)),
67 StdErr(err) => err,
68 };
69 CollectedErrs(StdErr(
70 iter::once(first_err)
71 .chain(iter.filter_map(|i| i.err()))
72 .collect(),
73 ))
74 }
75}
76
77#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
78pub struct CollectedRecoverables<T>(pub T);
79
80struct CollectSum<T>(T);
81
82impl<T, U> FromIterator<U> for CollectSum<T>
83where
84 T: iter::Sum<U>,
85{
86 fn from_iter<I: IntoIterator<Item = U>>(iter: I) -> Self {
87 CollectSum(iter.into_iter().sum())
88 }
89}
90
91struct CollectProduct<T>(T);
92
93impl<T, U> FromIterator<U> for CollectProduct<T>
94where
95 T: iter::Product<U>,
96{
97 fn from_iter<I: IntoIterator<Item = U>>(iter: I) -> Self {
98 CollectProduct(iter.into_iter().product())
99 }
100}
101
102#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
103#[must_use]
104pub enum Result<T, RE, FE> {
105 Ok(T),
106 Recoverable(RE),
107 Fatal(FE),
108}
109
110pub use crate::Result::*;
111
112impl<T, RE, FE> Result<T, RE, FE> {
113 pub fn from_std(value: StdResult<StdResult<T, RE>, FE>) -> Self {
114 match value {
115 StdOk(StdOk(ok)) => Ok(ok),
116 StdOk(StdErr(err)) => Recoverable(err),
117 StdErr(err) => Fatal(err),
118 }
119 }
120
121 pub fn from_split<E>(
122 split: impl FnOnce(E) -> StdResult<RE, FE>,
123 value: StdResult<T, E>,
124 ) -> Self {
125 match value {
126 StdOk(ok) => Ok(ok),
127 StdErr(err) => Self::from_err(split(err)),
128 }
129 }
130
131 pub fn ok_or_recoverable(value: StdResult<T, RE>) -> Self {
132 StdOk(value).into()
133 }
134
135 pub fn ok_or_fatal(value: StdResult<T, FE>) -> Self {
136 value.map(StdOk).into()
137 }
138
139 pub fn from_err(error: StdResult<RE, FE>) -> Self {
140 match error {
141 StdOk(err) => Recoverable(err),
142 StdErr(err) => Fatal(err),
143 }
144 }
145
146 pub fn to_std(self) -> StdResult<StdResult<T, RE>, FE> {
147 match self {
148 Ok(ok) => StdOk(StdOk(ok)),
149 Recoverable(err) => StdOk(StdErr(err)),
150 Fatal(err) => StdErr(err),
151 }
152 }
153
154 pub fn to_std_flipped(self) -> StdResult<T, StdResult<RE, FE>> {
155 match self {
156 Ok(ok) => StdOk(ok),
157 Recoverable(err) => StdErr(StdOk(err)),
158 Fatal(err) => StdErr(StdErr(err)),
159 }
160 }
161
162 pub const fn is_ok(&self) -> bool {
163 matches!(self, Ok(_))
164 }
165
166 pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
167 self.ok().map(f).unwrap_or(false)
168 }
169
170 pub const fn is_any_err(&self) -> bool {
171 !self.is_ok()
172 }
173
174 pub const fn is_recoverable(&self) -> bool {
175 matches!(self, Recoverable(_))
176 }
177
178 pub fn is_recoverable_and(self, f: impl FnOnce(RE) -> bool) -> bool {
179 self.recoverable().map(f).unwrap_or(false)
180 }
181
182 pub const fn is_fatal(&self) -> bool {
183 matches!(self, Fatal(_))
184 }
185
186 pub fn is_fatal_and(self, f: impl FnOnce(FE) -> bool) -> bool {
187 self.fatal().map(f).unwrap_or(false)
188 }
189
190 pub fn ok(self) -> Option<T> {
191 match self {
192 Ok(out) => Some(out),
193 _ => None,
194 }
195 }
196
197 pub fn recoverable(self) -> Option<RE> {
198 match self {
199 Recoverable(out) => Some(out),
200 _ => None,
201 }
202 }
203
204 pub fn fatal(self) -> Option<FE> {
205 match self {
206 Fatal(out) => Some(out),
207 _ => None,
208 }
209 }
210
211 pub fn non_fatal(self) -> Option<StdResult<T, RE>> {
212 match self {
213 Ok(out) => Some(StdOk(out)),
214 Recoverable(err) => Some(StdErr(err)),
215 Fatal(_) => None,
216 }
217 }
218
219 pub fn err(self) -> Option<StdResult<RE, FE>> {
220 match self {
221 Ok(_) => None,
222 Recoverable(err) => Some(StdOk(err)),
223 Fatal(err) => Some(StdErr(err)),
224 }
225 }
226
227 pub fn as_ref(&self) -> Result<&T, &RE, &FE> {
228 match self {
229 Ok(ok) => Ok(ok),
230 Recoverable(err) => Recoverable(err),
231 Fatal(err) => Fatal(err),
232 }
233 }
234
235 pub fn as_mut(&mut self) -> Result<&mut T, &mut RE, &mut FE> {
236 match self {
237 Ok(ok) => Ok(ok),
238 Recoverable(err) => Recoverable(err),
239 Fatal(err) => Fatal(err),
240 }
241 }
242
243 fn map_all<O, REO, FEO>(
244 self,
245 f: impl FnOnce(T) -> O,
246 g: impl FnOnce(RE) -> REO,
247 h: impl FnOnce(FE) -> FEO,
248 ) -> Result<O, REO, FEO> {
249 match self {
250 Ok(ok) => Ok(f(ok)),
251 Recoverable(err) => Recoverable(g(err)),
252 Fatal(err) => Fatal(h(err)),
253 }
254 }
255
256 pub fn map<O>(self, f: impl FnOnce(T) -> O) -> Result<O, RE, FE> {
257 self.map_all(f, |x| x, |x| x)
258 }
259
260 pub fn map_or<O>(self, default: O, f: impl FnOnce(T) -> O) -> O {
261 self.map(f).unwrap_or(default)
262 }
263
264 pub fn map_or_else<O>(self, default: impl FnOnce() -> O, f: impl FnOnce(T) -> O) -> O {
265 self.map(f).unwrap_or_else(default)
266 }
267
268 pub fn map_recoverable<REO>(self, f: impl FnOnce(RE) -> REO) -> Result<T, REO, FE> {
269 self.map_all(|x| x, f, |x| x)
270 }
271
272 pub fn map_fatal<FEO>(self, f: impl FnOnce(FE) -> FEO) -> Result<T, RE, FEO> {
273 self.map_all(|x| x, |x| x, f)
274 }
275
276 pub fn inspect(self, f: impl FnOnce(&T)) -> Self {
277 self.map(|x| {
278 f(&x);
279 x
280 })
281 }
282
283 pub fn inspect_recoverable(self, f: impl FnOnce(&RE)) -> Self {
284 self.map_recoverable(|x| {
285 f(&x);
286 x
287 })
288 }
289
290 pub fn inspect_fatal(self, f: impl FnOnce(&FE)) -> Self {
291 self.map_fatal(|x| {
292 f(&x);
293 x
294 })
295 }
296
297 pub fn as_deref(&self) -> Result<&T::Target, &RE, &FE>
298 where
299 T: ops::Deref,
300 {
301 self.as_ref().map_deref()
302 }
303
304 pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut RE, &mut FE>
305 where
306 T: ops::DerefMut,
307 {
308 self.as_mut().map_deref_mut()
309 }
310
311 pub fn iter(&self) -> core::option::IntoIter<&T> {
312 self.as_ref().ok().into_iter()
313 }
314
315 pub fn iter_mut(&mut self) -> core::option::IntoIter<&mut T> {
316 self.as_mut().ok().into_iter()
317 }
318
319 pub fn expect_nonfatal(self, msg: &str) -> LocalResult<T, RE>
320 where
321 FE: fmt::Debug,
322 {
323 self.to_std().expect(msg).into()
324 }
325
326 pub fn expect_ok(self, msg: &str) -> T
327 where
328 RE: fmt::Debug,
329 FE: fmt::Debug,
330 {
331 self.to_std().expect(msg).expect(msg)
332 }
333
334 pub fn unwrap_nonfatal(self) -> LocalResult<T, RE>
335 where
336 FE: fmt::Debug,
337 {
338 self.to_std().unwrap().into()
339 }
340
341 pub fn unwrap_ok(self) -> T
342 where
343 RE: fmt::Debug,
344 FE: fmt::Debug,
345 {
346 self.to_std().unwrap().unwrap()
347 }
348
349 pub fn unwrap_or_default(self) -> T
350 where
351 T: Default,
352 {
353 self.unwrap_or_else(T::default)
354 }
355
356 pub fn unwrap_or(self, default: T) -> T {
357 self.unwrap_or_else(move || default)
358 }
359
360 pub fn unwrap_or_else(self, default: impl FnOnce() -> T) -> T {
361 match self {
362 Ok(out) => out,
363 _ => default(),
364 }
365 }
366
367 pub fn and<O>(self, res: Result<O, RE, FE>) -> Result<O, RE, FE> {
368 self.and_then(move |_| res)
369 }
370
371 pub fn and_then<O>(self, f: impl FnOnce(T) -> Result<O, RE, FE>) -> Result<O, RE, FE> {
372 match self {
373 Ok(out) => f(out),
374 Recoverable(err) => Recoverable(err),
375 Fatal(err) => Fatal(err),
376 }
377 }
378
379 pub fn flatten_err<E: From<RE> + From<FE>>(self) -> StdResult<T, E> {
380 match self {
381 Ok(out) => StdOk(out),
382 Recoverable(err) => StdErr(err.into()),
383 Fatal(err) => StdErr(err.into()),
384 }
385 }
386
387 pub fn convert_err<REO: From<RE>, FEO: From<FE>>(self) -> Result<T, REO, FEO> {
388 match self {
389 Ok(out) => Ok(out),
390 Recoverable(err) => Recoverable(err.into()),
391 Fatal(err) => Fatal(err.into()),
392 }
393 }
394
395 pub fn more_fatal<REO>(self, f: impl FnOnce(RE) -> StdResult<REO, FE>) -> Result<T, REO, FE> {
396 match self {
397 Ok(out) => Ok(out),
398 Recoverable(err) => match f(err) {
399 StdOk(err) => Recoverable(err),
400 StdErr(err) => Fatal(err),
401 },
402 Fatal(err) => Fatal(err),
403 }
404 }
405
406 pub fn less_fatal<FEO>(self, f: impl FnOnce(FE) -> StdResult<RE, FEO>) -> Result<T, RE, FEO> {
407 match self {
408 Ok(out) => Ok(out),
409 Recoverable(err) => Recoverable(err),
410 Fatal(err) => match f(err) {
411 StdOk(err) => Recoverable(err),
412 StdErr(err) => Fatal(err),
413 },
414 }
415 }
416
417 pub fn collect_layered<U>(iter: impl IntoIterator<Item = Result<U, RE, FE>>) -> Self
418 where
419 T: FromIterator<U>,
420 {
421 let mut iter = iter.into_iter().map(Result::to_std);
422 let mut out: StdResult<_, _> = match (&mut iter).collect() {
423 StdOk(out) => out,
424 StdErr(err) => return Fatal(err),
425 };
426 for i in iter {
427 match i {
428 StdOk(StdOk(_)) => (),
429 StdOk(StdErr(recoverable)) if out.is_ok() => out = StdErr(recoverable),
430 StdOk(StdErr(_)) => (),
431 StdErr(err) => return Fatal(err),
432 }
433 }
434 Self::ok_or_recoverable(out)
435 }
436}
437
438impl<'a, T, RE, FE> Result<&'a T, RE, FE> {
439 pub fn map_deref(self) -> Result<&'a <T as ops::Deref>::Target, RE, FE>
440 where
441 T: ops::Deref,
442 {
443 self.map(|x| &**x)
444 }
445
446 pub fn copied(self) -> Result<T, RE, FE>
447 where
448 T: Copy,
449 {
450 self.map(|ok| *ok)
451 }
452
453 pub fn cloned(self) -> Result<T, RE, FE>
454 where
455 T: Clone,
456 {
457 self.map(|ok| ok.clone())
458 }
459}
460
461impl<'a, T, RE, FE> Result<&'a mut T, RE, FE> {
462 pub fn map_deref(self) -> Result<&'a T::Target, RE, FE>
463 where
464 T: ops::DerefMut,
465 {
466 self.map(|x| &**x)
467 }
468
469 pub fn map_deref_mut(self) -> Result<&'a mut T::Target, RE, FE>
470 where
471 T: ops::DerefMut,
472 {
473 self.map(|x| &mut **x)
474 }
475
476 pub fn copied(self) -> Result<T, RE, FE>
477 where
478 T: Copy,
479 {
480 self.map(|ok| *ok)
481 }
482
483 pub fn cloned(self) -> Result<T, RE, FE>
484 where
485 T: Clone,
486 {
487 self.map(|ok| ok.clone())
488 }
489}
490
491impl<T, RE, FE> Result<Result<T, RE, FE>, RE, FE> {
492 pub fn flatten(self) -> Result<T, RE, FE> {
493 self.and_then(|x| x)
494 }
495}
496
497impl<T, RE, FE> From<Result<T, RE, FE>> for StdResult<StdResult<T, RE>, FE> {
498 fn from(value: Result<T, RE, FE>) -> Self {
499 value.to_std()
500 }
501}
502
503impl<T, RE, FE> From<StdResult<StdResult<T, RE>, FE>> for Result<T, RE, FE> {
504 fn from(value: StdResult<StdResult<T, RE>, FE>) -> Self {
505 Self::from_std(value)
506 }
507}
508
509impl<T, RE, FE> IntoIterator for Result<T, RE, FE> {
510 type Item = T;
511 type IntoIter = core::option::IntoIter<T>;
512
513 fn into_iter(self) -> Self::IntoIter {
514 self.ok().into_iter()
515 }
516}
517
518impl<'a, T, RE, FE> IntoIterator for &'a Result<T, RE, FE> {
519 type Item = &'a T;
520 type IntoIter = core::option::IntoIter<&'a T>;
521
522 fn into_iter(self) -> Self::IntoIter {
523 self.iter()
524 }
525}
526
527impl<'a, T, RE, FE> IntoIterator for &'a mut Result<T, RE, FE> {
528 type Item = &'a mut T;
529 type IntoIter = core::option::IntoIter<&'a mut T>;
530
531 fn into_iter(self) -> Self::IntoIter {
532 self.iter_mut()
533 }
534}
535
536impl<T, RE, FE, C> FromIterator<Result<T, RE, FE>> for Result<C, RE, FE>
537where
538 C: FromIterator<T>,
539{
540 fn from_iter<I: IntoIterator<Item = Result<T, RE, FE>>>(iter: I) -> Self {
541 Self::from_std(iter.into_iter().map(Result::to_std).collect())
542 }
543}
544
545impl<T, RE, FE, C, REC, FEC> FromIterator<Result<T, RE, FE>> for CollectedErrs<Result<C, REC, FEC>>
546where
547 C: FromIterator<T>,
548 REC: FromIterator<RE>,
549 FEC: FromIterator<FE>,
550{
551 fn from_iter<I: IntoIterator<Item = Result<T, RE, FE>>>(iter: I) -> Self {
552 let collected: CollectedErrs<StdResult<CollectedErrs<StdResult<C, REC>>, FEC>> =
553 iter.into_iter().map(Result::to_std).collect();
554
555 CollectedErrs(collected.0.map(|collected| collected.0).into())
556 }
557}
558
559impl<T, RE, FE, C, EC> FromIterator<Result<T, RE, FE>> for CollectedErrs<StdResult<C, EC>>
560where
561 C: FromIterator<T>,
562 EC: FromIterator<StdResult<RE, FE>>,
563{
564 fn from_iter<I: IntoIterator<Item = Result<T, RE, FE>>>(iter: I) -> Self {
565 iter.into_iter().map(Result::to_std_flipped).collect()
566 }
567}
568
569impl<T, RE, FE, C, REC> FromIterator<Result<T, RE, FE>>
570 for CollectedRecoverables<Result<C, REC, FE>>
571where
572 C: FromIterator<T>,
573 REC: FromIterator<RE>,
574{
575 fn from_iter<I: IntoIterator<Item = Result<T, RE, FE>>>(iter: I) -> Self {
576 let collected: StdResult<CollectedErrs<StdResult<C, REC>>, FE> =
577 iter.into_iter().map(Result::to_std).collect();
578
579 CollectedRecoverables(collected.map(|collected| collected.0).into())
580 }
581}
582
583#[cfg(feature = "std")]
584impl<T: std::process::Termination, RE: fmt::Debug, FE: fmt::Debug> std::process::Termination
585 for Result<T, RE, FE>
586{
587 fn report(self) -> std::process::ExitCode {
588 self.to_std().report()
589 }
590}
591
592impl<T, RE, FE, FEO: From<FE>> ops::FromResidual<Result<Infallible, Infallible, FE>>
593 for Result<T, RE, FEO>
594{
595 fn from_residual(residual: Result<Infallible, Infallible, FE>) -> Self {
596 match residual {
597 Ok(infallible) | Recoverable(infallible) => match infallible {},
598 Fatal(err) => Fatal(err.into()),
599 }
600 }
601}
602
603impl<T, RE, FE> ops::Try for Result<T, RE, FE> {
604 type Output = LocalResult<T, RE>;
605 type Residual = Result<Infallible, Infallible, FE>;
606
607 fn from_output(output: Self::Output) -> Self {
608 match output {
609 NoErr(ok) => Ok(ok),
610 Handle(err) => Recoverable(err),
611 }
612 }
613
614 fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
615 match self {
616 Ok(ok) => ops::ControlFlow::Continue(NoErr(ok)),
617 Recoverable(err) => ops::ControlFlow::Continue(Handle(err)),
618 Fatal(err) => ops::ControlFlow::Break(Fatal(err)),
619 }
620 }
621}
622
623#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
624#[must_use]
625pub enum LocalResult<T, RE> {
626 NoErr(T),
627 Handle(RE),
628}
629
630pub use LocalResult::*;
631
632impl<T, RE> LocalResult<T, RE> {
633 pub fn from_std(res: StdResult<T, RE>) -> Self {
634 match res {
635 StdOk(ok) => NoErr(ok),
636 StdErr(err) => Handle(err),
637 }
638 }
639
640 pub fn to_std(self) -> StdResult<T, RE> {
641 match self {
642 NoErr(ok) => StdOk(ok),
643 Handle(err) => StdErr(err),
644 }
645 }
646
647 pub fn to_result<FE>(self) -> Result<T, RE, FE> {
648 Result::ok_or_recoverable(self.to_std())
649 }
650
651 pub const fn is_ok(&self) -> bool {
652 matches!(self, NoErr(_))
653 }
654
655 pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
656 self.ok().map(f).unwrap_or(false)
657 }
658
659 pub fn is_ok_or(self, f: impl FnOnce(RE) -> bool) -> bool {
660 self.err().map(f).unwrap_or(true)
661 }
662
663 pub const fn is_err(&self) -> bool {
664 !self.is_ok()
665 }
666
667 pub fn is_err_and(self, f: impl FnOnce(RE) -> bool) -> bool {
668 self.err().map(f).unwrap_or(false)
669 }
670
671 pub fn is_err_or(self, f: impl FnOnce(T) -> bool) -> bool {
672 self.ok().map(f).unwrap_or(true)
673 }
674
675 pub fn ok(self) -> Option<T> {
676 match self {
677 NoErr(out) => Some(out),
678 Handle(_) => None,
679 }
680 }
681
682 pub fn err(self) -> Option<RE> {
683 match self {
684 NoErr(_) => None,
685 Handle(err) => Some(err),
686 }
687 }
688
689 pub fn expect(self, msg: &str) -> T
690 where
691 RE: fmt::Debug,
692 {
693 self.to_std().expect(msg)
694 }
695
696 pub fn unwrap(self) -> T
697 where
698 RE: fmt::Debug,
699 {
700 self.to_std().unwrap()
701 }
702}
703
704impl<T, RE> From<LocalResult<T, RE>> for StdResult<T, RE> {
705 fn from(value: LocalResult<T, RE>) -> Self {
706 value.to_std()
707 }
708}
709
710impl<T, RE> From<StdResult<T, RE>> for LocalResult<T, RE> {
711 fn from(value: StdResult<T, RE>) -> Self {
712 Self::from_std(value)
713 }
714}
715
716impl<T, RE, FE> From<LocalResult<T, RE>> for Result<T, RE, FE> {
717 fn from(value: LocalResult<T, RE>) -> Self {
718 value.to_result()
719 }
720}
721
722impl<T, RE, REO: From<RE>> ops::FromResidual<LocalResult<Infallible, RE>> for LocalResult<T, REO> {
725 fn from_residual(residual: LocalResult<Infallible, RE>) -> Self {
726 match residual {
727 NoErr(infallible) => match infallible {},
728 Handle(err) => Handle(err.into()),
729 }
730 }
731}
732
733impl<T, RE> ops::Try for LocalResult<T, RE> {
734 type Output = T;
735 type Residual = LocalResult<Infallible, RE>;
736
737 fn from_output(output: Self::Output) -> Self {
738 NoErr(output)
739 }
740
741 fn branch(self) -> ops::ControlFlow<Self::Residual, Self::Output> {
742 match self {
743 NoErr(ok) => ops::ControlFlow::Continue(ok),
744 Handle(err) => ops::ControlFlow::Break(Handle(err)),
745 }
746 }
747}
748
749impl<T, FE, FEO: From<FE>> ops::FromResidual<Result<Infallible, Infallible, FE>>
751 for StdResult<T, FEO>
752{
753 fn from_residual(residual: Result<Infallible, Infallible, FE>) -> Self {
754 match residual {
755 Ok(infallible) | Recoverable(infallible) => match infallible {},
756 Fatal(err) => StdResult::Err(err.into()),
757 }
758 }
759}
760
761impl<T, RE, REO: From<RE>, FEO> ops::FromResidual<LocalResult<Infallible, RE>>
762 for StdResult<StdResult<T, REO>, FEO>
763{
764 fn from_residual(residual: LocalResult<Infallible, RE>) -> Self {
765 match residual {
766 NoErr(infallible) => match infallible {},
767 Handle(err) => StdResult::Ok(StdResult::Err(err.into())),
768 }
769 }
770}
771
772impl<T, FE, REO, FEO: From<FE>> ops::FromResidual<StdResult<Infallible, FE>>
774 for Result<T, REO, FEO>
775{
776 fn from_residual(residual: StdResult<Infallible, FE>) -> Self {
777 match residual {
778 StdOk(infallible) => match infallible {},
779 StdErr(err) => Fatal(err.into()),
780 }
781 }
782}
783
784impl<T, RE, FE, REO: From<RE>> ops::FromResidual<LocalResult<Infallible, RE>>
785 for Result<T, REO, FE>
786{
787 fn from_residual(residual: LocalResult<Infallible, RE>) -> Self {
788 match residual {
789 NoErr(infallible) => match infallible {},
790 Handle(err) => Recoverable(err.into()),
791 }
792 }
793}
794
795#[cfg(test)]
796mod tests {
797 use super::*;
798
799 #[test]
800 fn test_collected_errs_std() {
801 type Collected = CollectedErrs<StdResult<Vec<u8>, Vec<&'static str>>>;
802
803 let ok = StdOk::<u8, &'static str>;
804 let err = StdErr::<u8, &'static str>;
805
806 assert_eq!(
808 Vec::<StdResult<u8, &'static str>>::new()
809 .into_iter()
810 .collect::<Collected>(),
811 CollectedErrs(StdOk(Vec::new())),
812 );
813
814 assert_eq!(
816 vec![ok(1), ok(2), ok(3)].into_iter().collect::<Collected>(),
817 CollectedErrs(StdOk(vec![1, 2, 3]))
818 );
819
820 assert_eq!(
822 vec![err("A"), err("B"), err("C")]
823 .into_iter()
824 .collect::<Collected>(),
825 CollectedErrs(StdErr(vec!["A", "B", "C"])),
826 );
827
828 assert_eq!(
830 vec![ok(1), err("A"), err("B"), ok(2), err("C")]
831 .into_iter()
832 .collect::<Collected>(),
833 CollectedErrs(StdErr(vec!["A", "B", "C"])),
834 );
835 }
836
837 #[test]
838 fn test_collected_layered() {
839 type Collected = Result<Vec<u8>, &'static str, ()>;
840
841 assert_eq!(Collected::collect_layered([]), Ok(vec![]),);
843
844 assert_eq!(
846 Collected::collect_layered([Ok(1), Ok(2), Ok(3)]),
847 Ok(vec![1, 2, 3]),
848 );
849
850 assert_eq!(
852 Collected::collect_layered([Ok(1), Ok(2), Recoverable("X"), Ok(3)]),
853 Recoverable("X"),
854 );
855
856 assert_eq!(
858 Collected::collect_layered([Ok(1), Fatal(()), Ok(2), Recoverable("X"), Ok(3)]),
859 Fatal(()),
860 );
861
862 assert_eq!(
864 Collected::collect_layered([Ok(1), Recoverable("X"), Ok(2), Fatal(()), Ok(3)]),
865 Fatal(()),
866 );
867 }
868
869 #[test]
870 fn test_from_iter() {
871 type Collected = Result<Vec<u8>, &'static str, ()>;
872
873 assert_eq!(Collected::from_iter([]), Ok(vec![]),);
875
876 assert_eq!(
878 Collected::from_iter([Ok(1), Ok(2), Ok(3)]),
879 Ok(vec![1, 2, 3]),
880 );
881
882 assert_eq!(
884 Collected::from_iter([Ok(1), Ok(2), Recoverable("X"), Ok(3)]),
885 Recoverable("X"),
886 );
887
888 assert_eq!(
890 Collected::from_iter([Ok(1), Fatal(()), Ok(2), Recoverable("X"), Ok(3)]),
891 Fatal(()),
892 );
893
894 assert_eq!(
896 Collected::from_iter([Ok(1), Recoverable("X"), Ok(2), Fatal(()), Ok(3)]),
897 Recoverable("X"),
898 );
899 }
900
901 #[test]
902 fn test_from_collected_errs() {
903 type Collected = CollectedErrs<Result<Vec<u8>, Vec<&'static str>, Vec<()>>>;
904
905 assert_eq!(Collected::from_iter([]), CollectedErrs(Ok(vec![])),);
907
908 assert_eq!(
910 Collected::from_iter([Ok(1), Ok(2), Ok(3)]),
911 CollectedErrs(Ok(vec![1, 2, 3])),
912 );
913
914 assert_eq!(
916 Collected::from_iter([
917 Ok(1),
918 Ok(2),
919 Recoverable("X"),
920 Ok(3),
921 Recoverable("Y"),
922 Ok(4)
923 ]),
924 CollectedErrs(Recoverable(vec!["X", "Y"])),
925 );
926
927 assert_eq!(
929 Collected::from_iter([Ok(1), Fatal(()), Ok(2), Recoverable("X"), Ok(3)]),
930 CollectedErrs(Fatal(vec![()])),
931 );
932
933 assert_eq!(
935 Collected::from_iter([Ok(1), Recoverable("X"), Ok(2), Fatal(()), Ok(3)]),
936 CollectedErrs(Fatal(vec![()])),
937 );
938 }
939
940 #[test]
941 fn test_from_collected_errs_mixed() {
942 type Collected = CollectedErrs<StdResult<Vec<u8>, Vec<StdResult<&'static str, ()>>>>;
943
944 assert_eq!(
946 Collected::from_iter(Vec::<Result<u8, &'static str, ()>>::new()),
947 CollectedErrs(StdOk(vec![])),
948 );
949
950 assert_eq!(
952 Collected::from_iter([Ok(1), Ok(2), Ok(3)]),
953 CollectedErrs(StdOk(vec![1, 2, 3])),
954 );
955
956 assert_eq!(
958 Collected::from_iter([
959 Ok(1),
960 Ok(2),
961 Recoverable("X"),
962 Ok(3),
963 Recoverable("Y"),
964 Ok(4)
965 ]),
966 CollectedErrs(StdErr(vec![StdOk("X"), StdOk("Y")])),
967 );
968
969 assert_eq!(
971 Collected::from_iter([Ok(1), Fatal(()), Ok(2), Recoverable("X"), Ok(3)]),
972 CollectedErrs(StdErr(vec![StdErr(()), StdOk("X")])),
973 );
974 }
975
976 #[test]
977 fn test_from_collected_recoverables() {
978 type Collected = CollectedRecoverables<Result<Vec<u8>, Vec<&'static str>, ()>>;
979
980 assert_eq!(Collected::from_iter([]), CollectedRecoverables(Ok(vec![])),);
982
983 assert_eq!(
985 Collected::from_iter([Ok(1), Ok(2), Ok(3)]),
986 CollectedRecoverables(Ok(vec![1, 2, 3])),
987 );
988
989 assert_eq!(
991 Collected::from_iter([
992 Ok(1),
993 Ok(2),
994 Recoverable("X"),
995 Ok(3),
996 Recoverable("Y"),
997 Ok(4)
998 ]),
999 CollectedRecoverables(Recoverable(vec!["X", "Y"])),
1000 );
1001
1002 assert_eq!(
1004 Collected::from_iter([Ok(1), Fatal(()), Ok(2), Recoverable("X"), Ok(3)]),
1005 CollectedRecoverables(Fatal(())),
1006 );
1007
1008 assert_eq!(
1010 Collected::from_iter([Ok(1), Recoverable("X"), Ok(2), Fatal(()), Ok(3)]),
1011 CollectedRecoverables(Fatal(())),
1012 );
1013 }
1014
1015 mod type_checks {
1016 use super::*;
1017
1018 struct OkTy;
1019 struct RecoverableTy;
1020 struct FatalTy;
1021
1022 type NormalResultTy = StdResult<OkTy, FatalTy>;
1023 type StackedResultTy = StdResult<StdResult<OkTy, RecoverableTy>, FatalTy>;
1024 type ResultTy = Result<OkTy, RecoverableTy, FatalTy>;
1025
1026 fn std_result() -> NormalResultTy {
1027 unimplemented!()
1028 }
1029 fn result() -> ResultTy {
1030 unimplemented!()
1031 }
1032
1033 mod tests {
1034 #![allow(dead_code)]
1035 use super::*;
1036
1037 fn returns_std_result() -> StackedResultTy {
1038 std_result()?;
1039 match result()? {
1040 NoErr(_) | Handle(_) => (),
1041 }
1042 result()??;
1043
1044 StdOk(StdOk(OkTy))
1045 }
1046
1047 fn returns_result() -> ResultTy {
1048 std_result()?;
1049 match result()? {
1050 NoErr(_) | Handle(_) => (),
1051 }
1052 result()??;
1053
1054 Ok(OkTy)
1055 }
1056
1057 fn this_should_warn() -> ResultTy { result()?; Ok(OkTy) }
1059 }
1060 }
1061}