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}