collect_with/try_extract.rs
1use core::ops::ControlFlow;
2
3/// A trait for uniformly extracting success/error values from various container
4/// types.
5///
6/// This provides a generic interface to convert different outcome-carrying
7/// types into a standard [`Result`] form, enabling unified error handling
8/// across:
9/// - [`Result`] (by value and by reference)
10/// - [`Option`] (by value and by reference)
11/// - [`ControlFlow`] (by value and by reference)
12///
13/// The conversion preserves semantic meanings:
14/// - Success cases map to `Ok`
15/// - Termination/error cases map to `Err`
16pub trait TryExtract<'a> {
17 /// The type of success values (may be a reference)
18 type Ok;
19 /// The type of error values (may be a reference)
20 type Err;
21
22 /// Converts the container into a [`Result`], preserving semantic meaning
23 ///
24 /// For reference implementations (`&Result`, `&Option`, `&ControlFlow`),
25 /// this returns references to contained values rather than moving them
26 fn try_extract(self) -> Result<Self::Ok, Self::Err>;
27}
28
29// Core result implementations --------------------------------------
30impl<'a, T, E> TryExtract<'a> for Result<T, E> {
31 type Ok = T;
32 type Err = E;
33
34 /// Directly returns the owned Result (identity conversion)
35 fn try_extract(
36 self,
37 ) -> Result<
38 <Result<T, E> as TryExtract<'a>>::Ok,
39 <Result<T, E> as TryExtract<'a>>::Err,
40 > {
41 self
42 }
43}
44// Reference implementations ----------------------------------------
45impl<'a, T, E> TryExtract<'a> for &'a Result<T, E> {
46 type Ok = &'a T;
47 type Err = &'a E;
48
49 /// Extracts references to the contained value:
50 /// - &Result<Ok, Err> => Result<&Ok, &Err>
51 fn try_extract(self) -> Result<Self::Ok, Self::Err> {
52 self.as_ref()
53 }
54}
55
56// Option implementations -------------------------------------------
57impl<T> TryExtract<'_> for Option<T> {
58 type Ok = T;
59 type Err = ();
60
61 /// Converts an Option into a Result:
62 /// - Some(value) => Ok(value)
63 /// - None => Err(())
64 ///
65 /// This consumes the Option and moves the contained value
66 fn try_extract(self) -> Result<Self::Ok, Self::Err> {
67 self.ok_or(())
68 }
69}
70
71impl<'a, T> TryExtract<'a> for &'a Option<T> {
72 type Ok = &'a T;
73 type Err = ();
74
75 /// Extracts reference to the contained value if exists
76 /// - &Option:
77 /// - Some(value) => Ok(&value)
78 /// - None => Err(())
79 fn try_extract(self) -> Result<Self::Ok, Self::Err> {
80 self.as_ref().ok_or(())
81 }
82}
83
84// ControlFlow implementations --------------------------------------
85
86impl<C, B> TryExtract<'_> for ControlFlow<B, C> {
87 type Ok = C;
88 type Err = B;
89
90 /// Converts ControlFlow into Result:
91 /// - Continue(c) => Ok(c)
92 /// - Break(b) => Err(b)
93 #[inline]
94 fn try_extract(self) -> Result<Self::Ok, Self::Err> {
95 use ControlFlow::*;
96 match self {
97 Continue(c) => Ok(c),
98 Break(b) => Err(b),
99 }
100 }
101}
102
103impl<'a, C, B> TryExtract<'a> for &'a ControlFlow<B, C> {
104 type Ok = &'a C;
105 type Err = &'a B;
106
107 /// Extracts references from ControlFlow:
108 /// - Continue(c) => Ok(&c)
109 /// - Break(b) => Err(&b)
110 #[inline]
111 fn try_extract(self) -> Result<Self::Ok, Self::Err> {
112 match self {
113 ControlFlow::Continue(c) => Ok(c),
114 ControlFlow::Break(b) => Err(b),
115 }
116 }
117}