deep_flatten2/
lib.rs

1pub use deep_flatten::OptionDeepFlatten;
2
3/// Deeply converts self into an [Option<T>], consuming self, and discarding any errors.
4pub trait ResultDeepOk<T> {
5    /// Convert nested Results e.g. `Result<Result<Result<T, E1>, E2>, E3>` into Option<T>, discarding any errors.
6    /// Can convert up to 32 Results.
7    fn deep_ok(self) -> Option<T>;
8}
9
10macro_rules! __impl_result {
11    ($_ignored:ident) => {};
12    ($_ignored:ident $($t:ident)+) => {
13        impl<T, $($t),+> ResultDeepOk<T> for __impl_result!(@nest_result $($t)+) {
14            fn deep_ok(self) -> Option<T> {
15                match self {
16                    __impl_result!(@nest_ok(inner) $($t)+) => Some(inner),
17                    _ => None,
18                }
19            }
20        }
21        __impl_result!($($t)*);
22    };
23
24    (@nest_result $e:ident) => { Result<T, $e> };
25    (@nest_result $e:ident $($t:ident)+) => {
26        Result<__impl_result!(@nest_result $($t)+), $e>
27    };
28    (@nest_ok($dst:ident) $($_ignored:ident)?) => { Ok($dst) };
29    (@nest_ok($dst:ident) $_ignored:ident $($t:ident)+) => {
30        Ok(__impl_result!(@nest_ok($dst) $($t)+))
31    };
32}
33
34// Impl for up to 32 Results.
35__impl_result!(IGNORED
36    E32
37    E31
38    E30
39    E29
40    E28
41    E27
42    E26
43    E25
44    E24
45    E23
46    E22
47    E21
48    E20
49    E19
50    E18
51    E17
52    E16
53    E15
54    E14
55    E13
56    E12
57    E11
58    E10
59    E9
60    E8
61    E7
62    E6
63    E5
64    E4
65    E3
66    E2
67    E1
68);
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_result_deep_ok() {
76        let x: Result<Result<i32, &str>, &str> = Ok(Ok(1));
77        let x2: Result<Result<i32, String>, &str> = Ok(Ok(1));
78        let y: Result<Result<Result<i32, &str>, String>, i32> = Ok(Ok(Ok(1)));
79        let z: Result<Result<Result<Result<i64, &str>, String>, i32>, bool> = Ok(Ok(Ok(Ok(1))));
80
81        assert_eq!(x.deep_ok(), Some(1));
82        assert_eq!(x2.deep_ok(), Some(1));
83        assert_eq!(y.deep_ok(), Some(1));
84        assert_eq!(z.deep_ok(), Some(1));
85
86        let y: Result<Result<Result<i32, &str>, &str>, &str> = Ok(Ok(Ok(1)));
87        let z: Result<Result<Result<Result<i64, &str>, &str>, &str>, &str> = Ok(Ok(Ok(Ok(1))));
88
89        assert_eq!(y.deep_ok(), Some(1));
90        assert_eq!(z.deep_ok(), Some(1));
91    }
92
93    #[test]
94    fn test_result_deep_ok_err() {
95        let x: Result<Result<i32, &str>, &str> = Err("error");
96        let x2: Result<Result<i32, String>, &str> = Ok(Err("error".to_string()));
97        let y: Result<Result<Result<i32, &str>, String>, i32> = Err(1);
98        let z: Result<Result<Result<Result<i64, &str>, String>, i32>, bool> =
99            Ok(Ok(Err("1".to_string())));
100
101        assert_eq!(x.deep_ok(), None::<i32>);
102        assert_eq!(x2.deep_ok(), None::<i32>);
103        assert_eq!(y.deep_ok(), None::<i32>);
104        assert_eq!(z.deep_ok(), None::<i64>);
105    }
106}