1pub use deep_flatten::OptionDeepFlatten;
2
3pub trait ResultDeepOk<T> {
5 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_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}