Skip to content

Instantly share code, notes, and snippets.

@thepowersgang
Last active February 27, 2016 03:59
Show Gist options
  • Save thepowersgang/f0de63db1746114266d3 to your computer and use it in GitHub Desktop.
Save thepowersgang/f0de63db1746114266d3 to your computer and use it in GitHub Desktop.
mod ops
{
/// Root trait for the `?` operator (defined below as `qm!`)
pub trait Try<ReturnType>
{
/// Success return type
type Result;
/// Convert this type into a result or a return value.
fn try(self) -> OrReturn<Self::Result, ReturnType>;
}
/// Result-like enum used only for Try+qm!/?
pub enum OrReturn<V, R> {
Value(V),
Return(R)
}
}
/// Question Mark (`?`) operator implementation with a macro
macro_rules! qm {
($e:expr) => {
match ::ops::Try::try($e) {
::ops::OrReturn::Value(v) => v,
::ops::OrReturn::Return(e) => return e,
}
};
}
/// Same behavior as the existing `try!` macro
impl<T,E,RT,RE> ::ops::Try<Result<RT,RE>> for Result<T,E>
where
RE: From<E>
{
type Result = T;
fn try(self) -> ::ops::OrReturn<T, Result<RT,RE>> {
match self
{
Ok(v) => ::ops::OrReturn::Value(v),
Err(e) => ::ops::OrReturn::Return( Err(From::from(e)) ),
}
}
}
/// A `?` implementation to return None if the result was None
impl<T,U> ::ops::Try<Option<U>> for Option<T>
{
type Result = T;
fn try(self) -> ::ops::OrReturn<T, Option<U>> {
match self
{
Some(v) => ::ops::OrReturn::Value(v),
None => ::ops::OrReturn::Return(None),
}
}
}
fn main() {
}
fn res_test(f: &mut ::std::io::Read) -> ::std::io::Result<u32> {
let mut buf = [0; 4];
let out = qm!( f.read(&mut buf) );
Ok(out as u32)
}
fn option_test(val: Option<u32>) -> Option<u8> {
let v = qm!( val );
if v < 256 {
Some(v as u8)
}
else {
None
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment