use std::convert::From; #[macro_export] macro_rules! try { ($expression: expr) => { match $crate::Triable::try($expression) { $crate::TriableResult::Expression(value) => value, $crate::TriableResult::EarlyReturn(value) => return value, } }; } pub enum TriableResult { Expression(Expr), EarlyReturn(Return), } pub trait Triable { fn try(self) -> TriableResult; } impl Triable> for Result where Err2: From { fn try(self) -> TriableResult> { match self { Ok(value) => TriableResult::Expression(value), Err(error) => TriableResult::EarlyReturn(Err(From::from(error))) } } } impl Triable> for Option { fn try(self) -> TriableResult> { match self { Some(value) => TriableResult::Expression(value), None => TriableResult::EarlyReturn(None) } } } impl Triable> for Option { fn try(self) -> TriableResult> { match self { Some(value) => TriableResult::Expression(value), None => TriableResult::EarlyReturn(Err(())) } } } impl Triable> for Result { fn try(self) -> TriableResult> { match self { Ok(value) => TriableResult::Expression(value), Err(()) => TriableResult::EarlyReturn(None) } } } impl Triable<(), bool> for bool { fn try(self) -> TriableResult<(), bool> { if self { TriableResult::Expression(()) } else { TriableResult::EarlyReturn(false) } } } impl Triable for Result { fn try(self) -> TriableResult { match self { Ok(value) => TriableResult::Expression(value), Err(()) => TriableResult::EarlyReturn(false) } } } impl Triable for Option { fn try(self) -> TriableResult { match self { Some(value) => TriableResult::Expression(value), None => TriableResult::EarlyReturn(false) } } } impl Triable<(), Result> for bool { fn try(self) -> TriableResult<(), Result> { if self { TriableResult::Expression(()) } else { TriableResult::EarlyReturn(Err(())) } } } impl Triable<(), Option> for bool { fn try(self) -> TriableResult<(), Option> { if self { TriableResult::Expression(()) } else { TriableResult::EarlyReturn(None) } } } #[test] fn result() { fn ok() -> Result { Ok(try!(Ok(4))) } assert_eq!(ok(), Ok(4)); fn err() -> Result { Ok(try!(Err(()))) } assert_eq!(err(), Err(())); } #[test] fn option() { fn some() -> Option { Some(try!(Some(5))) } assert_eq!(some(), Some(5)); fn none() -> Option { Some(try!(None)) } assert_eq!(none(), None); } #[test] fn option_to_result() { fn ok() -> Result { Ok(try!(Some(4))) } assert_eq!(ok(), Ok(4)); fn err() -> Result { Ok(try!(None)) } assert_eq!(err(), Err(())); } #[test] fn result_to_option() { fn some() -> Option { Some(try!(Ok(5))) } assert_eq!(some(), Some(5)); fn none() -> Option { Some(try!(Err(()))) } assert_eq!(none(), None); } #[test] fn bool() { fn true_() -> bool { try!(true); true } assert_eq!(true_(), true); fn false_() -> bool { try!(false); true } assert_eq!(false_(), false); } #[test] fn option_to_bool() { fn true_() -> bool { try!(Some(5)); true } assert_eq!(true_(), true); fn false_() -> bool { try!(None); true } assert_eq!(false_(), false); } #[test] fn result_to_bool() { fn true_() -> bool { try!(Ok(5)); true } assert_eq!(true_(), true); fn false_() -> bool { try!(Err(())); true } assert_eq!(false_(), false); } #[test] fn bool_to_result() { fn ok() -> Result<(), ()> { Ok(try!(true)) } assert_eq!(ok(), Ok(())); fn err() -> Result<(), ()> { Ok(try!(false)) } assert_eq!(err(), Err(())); } #[test] fn bool_to_option() { fn some() -> Option<()> { Some(try!(true)) } assert_eq!(some(), Some(())); fn none() -> Option<()> { Some(try!(false)) } assert_eq!(none(), None); }