try_v2_traits/extract.rs
1use std::{
2 fmt::Debug,
3 ops::{ControlFlow, Try},
4};
5
6impl<T> Extract<T> for Option<T> {}
7impl<T, E> Extract<T> for Result<T, E> {}
8impl<B, C> Extract<C> for ControlFlow<B, C> {}
9
10/// Methods for extracting the wrapped value
11pub trait Extract<T>
12where
13 Self: Try<Output = T> + Sized,
14{
15 /// Extracts the contained value `v` returning `Some(v)`, or `None` in the case of a Residual
16 ///
17 /// Think of this as the non-panicking version of `unwrap()`
18 fn output(self) -> Option<T> {
19 match self.branch() {
20 ControlFlow::Continue(val) => Some(val),
21 ControlFlow::Break(_) => None,
22 }
23 }
24
25 /// Return the contained value or panic with a generic message.
26 ///
27 /// In general you should prefer `expect()` for panic situations or `output()` for non-panic
28 ///
29 /// # Note to implementors
30 /// - the provided implementation uses [`Extract::expect`]. Implementors should prefer
31 /// customising `expect` to directly customising `unwrap`.
32 fn unwrap(self) -> T
33 where
34 Self::Residual: Debug,
35 {
36 self.expect("called `unwrap()` on a residual:")
37 }
38
39 /// Return the contained value or panic with a custom message.
40 ///
41 /// In general you should prefer `output()` or `?` which do not panic.
42 fn expect(self, msg: &str) -> T
43 where
44 Self::Residual: Debug,
45 {
46 match self.branch() {
47 ControlFlow::Continue(v) => v,
48 #[cfg(not(panic = "immediate-abort"))]
49 ControlFlow::Break(r) => panic!("{msg}: {r:?}"),
50 #[cfg(panic = "immediate-abort")]
51 ControlFlow::Break(_) => panic!(),
52 }
53 }
54
55 /// Return the contained value or the given default.
56 ///
57 /// Arguments passed to unwrap_or are eagerly evaluated; if you are passing the result of a
58 /// function call, it is recommended to use unwrap_or_else, which is lazily evaluated.
59 ///
60 /// # Note to implementors
61 /// - the provided implementation uses [`Extract::unwrap_or_else`]. Implementors should prefer
62 /// customising `unwrap_or_else` to directly customising `unwrap_or`.
63 fn unwrap_or(self, default: T) -> T {
64 self.unwrap_or_else(|| default)
65 }
66
67 /// Return the contained value or a default. Requires `T` to implement `Default`
68 ///
69 /// # Note to implementors
70 /// - the provided implementation uses [`Extract::unwrap_or_else`]. Implementors should prefer
71 /// customising `unwrap_or_else` to directly customising `unwrap_or_default`.
72 fn unwrap_or_default(self) -> T
73 where
74 T: Default,
75 {
76 self.unwrap_or_else(Default::default)
77 }
78
79 /// Return the contained value or a value computed from a closure.
80 fn unwrap_or_else<F>(self, f: F) -> T
81 where
82 F: FnOnce() -> T,
83 {
84 match self.branch() {
85 ControlFlow::Continue(v) => v,
86 ControlFlow::Break(_) => f(),
87 }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 mod output {
96 use super::*;
97
98 #[test]
99 fn ok() {
100 let ok_5: Result<_, ()> = Ok(5);
101 let stdlib = ok_5.ok();
102 let custom = ok_5.output();
103 assert_eq!(stdlib, custom);
104 }
105 }
106}