#![cfg_attr(feature = "unstable", feature(macro_at_most_once_rep))]
#[macro_use]
extern crate partial_fn;
use partial_fn::PartialFn;
#[derive(Debug)]
enum Test {
Foo(i32),
Bar(f32),
Baz(bool),
}
macro_rules! test_partial_fn (
($var:expr, $lhs:expr, None) => (
assert!(!$var.is_defined_at($lhs) && $var.call($lhs).is_none())
);
($var:expr, $lhs:expr, $rhs:expr) => (
assert!($var.is_defined_at($lhs) &&
$var.call($lhs).is_some() &&
$var.call($lhs) == Some($rhs)
)
);
);
#[test]
fn handles_basic_functionality()
{
let pf = partial_fn!
{
"foo" => 1,
"bar" => 2
};
test_partial_fn!(pf, "foo", 1);
test_partial_fn!(pf, "bar", 2);
test_partial_fn!(pf, "baz", None);
}
#[test]
fn handles_basic_functionality_with_default_case()
{
let pf = partial_fn!
{
"foo" => 1,
"bar" => 2,
_ => 3
};
test_partial_fn!(pf, "foo", 1);
test_partial_fn!(pf, "bar", 2);
test_partial_fn!(pf, "baz", 3);
}
#[test]
fn handles_variable_capture()
{
let pf = partial_fn!
{
Test::Foo(a) => a,
Test::Bar(_b) => 1
};
test_partial_fn!(pf, Test::Foo(2), 2);
test_partial_fn!(pf, Test::Bar(1.0), 1);
test_partial_fn!(pf, Test::Baz(true), None);
}
#[test]
fn handles_non_local_variable_in_expression()
{
let c = 1;
let pf = partial_fn!
{
Test::Foo(a) => a + c
};
test_partial_fn!(pf, Test::Foo(1), 2);
test_partial_fn!(pf, Test::Bar(1.0), None);
}
#[test]
fn handles_pattern_guards()
{
let c1 = 1;
let c2 = 2;
let pf = partial_fn!
{
Test::Foo(a) if a == 1 => a + c1,
Test::Foo(a) if a == 2 => a + c2
};
test_partial_fn!(pf, Test::Foo(1), 2);
test_partial_fn!(pf, Test::Foo(2), 4);
test_partial_fn!(pf, Test::Foo(3), None);
test_partial_fn!(pf, Test::Bar(1.0), None);
}
#[test]
fn handles_pattern_alternation()
{
let pf = partial_fn!
{
1 | 2 => "foo",
3 => "bar"
};
test_partial_fn!(pf, 1, "foo");
test_partial_fn!(pf, 2, "foo");
test_partial_fn!(pf, 3, "bar");
test_partial_fn!(pf, 4, None);
}
#[test]
fn handles_inclusive_range()
{
let pf = partial_fn!
{
1..=3 => "foo"
};
test_partial_fn!(pf, 1, "foo");
test_partial_fn!(pf, 2, "foo");
test_partial_fn!(pf, 3, "foo");
test_partial_fn!(pf, 4, None);
}
#[test]
fn handles_pattern_binding()
{
let pf = partial_fn!
{
a @ "foo" => a
};
test_partial_fn!(pf, "foo", "foo");
test_partial_fn!(pf, "bar", None);
}
#[test]
fn handles_all_of_it_mixed_together()
{
let pf = partial_fn!
{
a @ 1..=10 | a @ 21..=30 if a % 2 == 0 => a/2,
a @ 11..=20 | a @ 31..=40 if a % 2 == 1 => a
};
test_partial_fn!(pf, 1, None);
test_partial_fn!(pf, 2, 1);
test_partial_fn!(pf, 11, 11);
test_partial_fn!(pf, 12, None);
test_partial_fn!(pf, 21, None);
test_partial_fn!(pf, 22, 11);
test_partial_fn!(pf, 31, 31);
test_partial_fn!(pf, 32, None);
}