pub trait IntoResult<T, E> {
fn into_result(self) -> Result<T, E>;
}
impl<T, E> IntoResult<T, E> for Result<T, E> {
#[inline]
fn into_result(self) -> Result<T, E> {
self
}
}
impl<T> IntoResult<T, ()> for Option<T> {
#[inline]
fn into_result(self) -> Result<T, ()> {
self.ok_or(())
}
}
#[macro_export]
macro_rules! inner {
($x:expr, if $i:path, else |$e:ident| $b:expr) => {{
match $x {
$i(q) => q,
$e @ _ => $b,
}
}};
($x:expr, if $i:path, else $b:expr) => {{
match $x {
$i(q) => q,
_ => $b,
}
}};
($x:expr, else |$e:ident| $b:expr) => {{
use $crate::IntoResult;
match $x.into_result() {
Ok(q) => q,
Err($e) => $b,
}
}};
($x:expr, else $b:expr) => {{
use $crate::IntoResult;
match $x.into_result() {
Ok(q) => q,
_ => $b,
}
}};
($x:expr, if $i:path) => {{
match $x {
$i(q) => q,
_ => panic!("Unexpected value found inside '{}'", stringify!($x)),
}
}};
($x:expr) => {{
use $crate::IntoResult;
match $x.into_result() {
Ok(q) => q,
_ => panic!("Unexpected value found inside '{}'", stringify!($x)),
}
}};
}
#[macro_export]
macro_rules! some {
($x:expr, if $i:path, else |$e:ident| $b:expr) => {{
match $x {
$i(q) => Some(q),
$e @ _ => $b,
}
}};
($x:expr, if $i:path, else $b:expr) => {{
match $x {
$i(q) => Some(q),
_ => $b,
}
}};
($x:expr, if $i:path) => {{
match $x {
$i(q) => Some(q),
_ => None,
}
}};
}
#[macro_export]
macro_rules! ok {
($x:expr, if $i:path, else |$e:ident| $b:expr) => {{
match $x {
$i(q) => Ok(q),
$e @ _ => $b,
}
}};
($x:expr, if $i:path, else $b:expr) => {{
match $x {
$i(q) => Ok(q),
_ => $b,
}
}};
($x:expr, if $i:path, or |$e:ident| $b:expr) => {{
match $x {
$i(q) => Ok(q),
$e @ _ => Err($b),
}
}};
($x:expr, if $i:path, or $b:expr) => {{
match $x {
$i(q) => Ok(q),
_ => Err($b),
}
}};
($x:expr, if $i:path) => {{
match $x {
$i(q) => Ok(q),
n @ _ => Err(n),
}
}};
}
#[test]
fn simple_opt() {
assert_eq!(inner!(Some(7)), 7);
}
#[test]
#[should_panic]
fn simple_opt_fail() {
let z: Option<i32> = None;
inner!(z);
}
#[test]
fn else_clause() {
let x: Result<String, i32> = Err(7);
let _ = inner!(x, else return);
panic!();
}
#[test]
fn else_clause_2() {
let x: Result<String, i32> = Err(7);
let y = inner!(x, else |e| {
assert_eq!(e, 7);
(e + 2).to_string()
});
assert_eq!(&y, "9");
}
#[test]
fn apple() {
enum Fruit {
Apple(i32),
_Orange(i16),
}
let z = Fruit::Apple(15);
assert_eq!(15, inner!(z, if Fruit::Apple));
}
#[test]
fn if_else() {
enum Fruit {
Apple(i32),
_Orange(i16),
}
let z = Fruit::Apple(15);
assert_eq!(15, inner!(z, if Fruit::Apple, else panic!("Not an apple")));
}
#[test]
fn own_enum() {
#[derive(Debug, PartialEq, Eq)]
enum Fruit {
Apple(i32),
Orange(i16),
}
impl IntoResult<i32, i16> for Fruit {
fn into_result(self) -> Result<i32, i16> {
match self {
Fruit::Apple(i) => Ok(i),
Fruit::Orange(i) => Err(i),
}
}
}
let z = Fruit::Orange(15);
assert_eq!(7, inner!(z, else |e| (e - 8) as i32));
let z = Fruit::Apple(15);
assert_eq!(
9,
inner!(z, if Fruit::Orange, else |e| {
assert_eq!(e, Fruit::Apple(15));
9
})
);
}
#[test]
fn some() {
#[derive(Debug, PartialEq, Eq)]
enum Fruit {
Apple(i32),
Orange(i16),
}
assert_eq!(some!(Fruit::Apple(15), if Fruit::Apple), Some(15));
assert_eq!(some!(Fruit::Orange(15), if Fruit::Apple), None);
assert_eq!(
some!(Fruit::Orange(15), if Fruit::Apple, else |e| {
assert_eq!(e, Fruit::Orange(15));
Some(30)
}),
Some(30)
);
}
#[test]
fn ok() {
#[derive(Debug, PartialEq, Eq)]
enum Fruit {
Apple(i32),
Orange(i16),
}
assert_eq!(ok!(Fruit::Apple(15), if Fruit::Apple), Ok(15));
assert_eq!(
ok!(Fruit::Orange(15), if Fruit::Apple),
Err(Fruit::Orange(15))
);
assert_eq!(
ok!(Fruit::Orange(15), if Fruit::Apple, else |e| {
assert_eq!(e, Fruit::Orange(15));
Err(3)
}),
Err(3)
);
assert_eq!(ok!(Fruit::Apple(15), if Fruit::Orange, or 67), Err(67));
assert_eq!(ok!(Fruit::Apple(15), if Fruit::Apple, or 67), Ok(15));
}