1 use std::convert::From;
2
3
4 #[macro_export]
5 macro_rules! try {
6 ($expression: expr) => {
7 match $crate::Triable::try($expression) {
8 $crate::TriableResult::Expression(value) => value,
9 $crate::TriableResult::EarlyReturn(value) => return value,
10 }
11 };
12 }
13
14
15 pub enum TriableResult<Expr, Return> {
16 Expression(Expr),
17 EarlyReturn(Return),
18 }
19
20
21 pub trait Triable<Expr, Return> {
try(self) -> TriableResult<Expr, Return>22 fn try(self) -> TriableResult<Expr, Return>;
23 }
24
25
26 impl<T1, T2, Err1, Err2> Triable<T1, Result<T2, Err2>> for Result<T1, Err1>
27 where Err2: From<Err1> {
try(self) -> TriableResult<T1, Result<T2, Err2>>28 fn try(self) -> TriableResult<T1, Result<T2, Err2>> {
29 match self {
30 Ok(value) => TriableResult::Expression(value),
31 Err(error) => TriableResult::EarlyReturn(Err(From::from(error)))
32 }
33 }
34 }
35
36
37 impl<T1, T2> Triable<T1, Option<T2>> for Option<T1> {
try(self) -> TriableResult<T1, Option<T2>>38 fn try(self) -> TriableResult<T1, Option<T2>> {
39 match self {
40 Some(value) => TriableResult::Expression(value),
41 None => TriableResult::EarlyReturn(None)
42 }
43 }
44 }
45
46
47 impl<T1, T2> Triable<T1, Result<T2, ()>> for Option<T1> {
try(self) -> TriableResult<T1, Result<T2, ()>>48 fn try(self) -> TriableResult<T1, Result<T2, ()>> {
49 match self {
50 Some(value) => TriableResult::Expression(value),
51 None => TriableResult::EarlyReturn(Err(()))
52 }
53 }
54 }
55
56
57 impl<T1, T2> Triable<T1, Option<T2>> for Result<T1, ()> {
try(self) -> TriableResult<T1, Option<T2>>58 fn try(self) -> TriableResult<T1, Option<T2>> {
59 match self {
60 Ok(value) => TriableResult::Expression(value),
61 Err(()) => TriableResult::EarlyReturn(None)
62 }
63 }
64 }
65
66
67 impl Triable<(), bool> for bool {
try(self) -> TriableResult<(), bool>68 fn try(self) -> TriableResult<(), bool> {
69 if self {
70 TriableResult::Expression(())
71 } else {
72 TriableResult::EarlyReturn(false)
73 }
74 }
75 }
76
77 impl<T> Triable<T, bool> for Result<T, ()> {
try(self) -> TriableResult<T, bool>78 fn try(self) -> TriableResult<T, bool> {
79 match self {
80 Ok(value) => TriableResult::Expression(value),
81 Err(()) => TriableResult::EarlyReturn(false)
82 }
83 }
84 }
85
86 impl<T> Triable<T, bool> for Option<T> {
try(self) -> TriableResult<T, bool>87 fn try(self) -> TriableResult<T, bool> {
88 match self {
89 Some(value) => TriableResult::Expression(value),
90 None => TriableResult::EarlyReturn(false)
91 }
92 }
93 }
94
95 impl<T> Triable<(), Result<T, ()>> for bool {
try(self) -> TriableResult<(), Result<T, ()>>96 fn try(self) -> TriableResult<(), Result<T, ()>> {
97 if self {
98 TriableResult::Expression(())
99 } else {
100 TriableResult::EarlyReturn(Err(()))
101 }
102 }
103 }
104
105
106 impl<T> Triable<(), Option<T>> for bool {
try(self) -> TriableResult<(), Option<T>>107 fn try(self) -> TriableResult<(), Option<T>> {
108 if self {
109 TriableResult::Expression(())
110 } else {
111 TriableResult::EarlyReturn(None)
112 }
113 }
114 }
115
116
117
118
119 #[test]
result()120 fn result() {
121 fn ok() -> Result<i32, ()> {
122 Ok(try!(Ok(4)))
123 }
124 assert_eq!(ok(), Ok(4));
125
126 fn err() -> Result<i32, ()> {
127 Ok(try!(Err(())))
128 }
129 assert_eq!(err(), Err(()));
130 }
131
132 #[test]
option()133 fn option() {
134 fn some() -> Option<i32> {
135 Some(try!(Some(5)))
136 }
137 assert_eq!(some(), Some(5));
138
139 fn none() -> Option<i32> {
140 Some(try!(None))
141 }
142 assert_eq!(none(), None);
143 }
144
145 #[test]
option_to_result()146 fn option_to_result() {
147 fn ok() -> Result<i32, ()> {
148 Ok(try!(Some(4)))
149 }
150 assert_eq!(ok(), Ok(4));
151
152 fn err() -> Result<i32, ()> {
153 Ok(try!(None))
154 }
155 assert_eq!(err(), Err(()));
156 }
157
158 #[test]
result_to_option()159 fn result_to_option() {
160 fn some() -> Option<i32> {
161 Some(try!(Ok(5)))
162 }
163 assert_eq!(some(), Some(5));
164
165 fn none() -> Option<i32> {
166 Some(try!(Err(())))
167 }
168 assert_eq!(none(), None);
169 }
170
171 #[test]
bool()172 fn bool() {
173 fn true_() -> bool {
174 try!(true);
175 true
176 }
177 assert_eq!(true_(), true);
178
179 fn false_() -> bool {
180 try!(false);
181 true
182 }
183 assert_eq!(false_(), false);
184 }
185
186 #[test]
option_to_bool()187 fn option_to_bool() {
188 fn true_() -> bool {
189 try!(Some(5));
190 true
191 }
192 assert_eq!(true_(), true);
193
194 fn false_() -> bool {
195 try!(None);
196 true
197 }
198 assert_eq!(false_(), false);
199 }
200
201 #[test]
result_to_bool()202 fn result_to_bool() {
203 fn true_() -> bool {
204 try!(Ok(5));
205 true
206 }
207 assert_eq!(true_(), true);
208
209 fn false_() -> bool {
210 try!(Err(()));
211 true
212 }
213 assert_eq!(false_(), false);
214 }
215
216 #[test]
bool_to_result()217 fn bool_to_result() {
218 fn ok() -> Result<(), ()> {
219 Ok(try!(true))
220 }
221 assert_eq!(ok(), Ok(()));
222
223 fn err() -> Result<(), ()> {
224 Ok(try!(false))
225 }
226 assert_eq!(err(), Err(()));
227 }
228
229 #[test]
bool_to_option()230 fn bool_to_option() {
231 fn some() -> Option<()> {
232 Some(try!(true))
233 }
234 assert_eq!(some(), Some(()));
235
236 fn none() -> Option<()> {
237 Some(try!(false))
238 }
239 assert_eq!(none(), None);
240 }
241