#![cfg_attr(feature = "unstable", feature(fn_traits))]
#![cfg_attr(feature = "unstable", feature(unboxed_closures))]
pub struct PartialFn<'a, A, B>
{
__call_fn: Box<dyn Fn(A) -> Option<B> + 'a>,
__is_defined_at_fn: Box<dyn Fn(A) -> bool + 'a>,
}
impl<'a, A, B> PartialFn<'a, A, B>
{
pub fn call(&self, arg: A) -> Option<B>
{
(*self.__call_fn)(arg)
}
pub fn is_defined_at(&self, arg: A) -> bool
{
(*self.__is_defined_at_fn)(arg)
}
#[doc(hidden)]
pub fn new(
call: Box<dyn Fn(A) -> Option<B> + 'a>,
defined: Box<dyn Fn(A) -> bool + 'a>,
) -> PartialFn<'a, A, B>
{
PartialFn
{
__call_fn: call,
__is_defined_at_fn: defined,
}
}
}
#[cfg(feature = "unstable")]
impl<'a, A, B> Fn<(A,)> for PartialFn<'a, A, B>
{
extern "rust-call" fn call(&self, (arg,): (A,)) -> Self::Output {
(*self.__call_fn)(arg)
}
}
#[cfg(feature = "unstable")]
impl<'a, A, B> FnMut<(A,)> for PartialFn<'a, A, B>
{
extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> Self::Output {
(*self.__call_fn)(arg)
}
}
#[cfg(feature = "unstable")]
impl<'a, A, B> FnOnce<(A,)> for PartialFn<'a, A, B>
{
type Output = Option<B>;
extern "rust-call" fn call_once(self, (arg,): (A,)) -> Self::Output
{
(*self.__call_fn)(arg)
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __call_macro
{
($($($pat:pat_param)|+ $(if $cond:expr)? => $result:expr),*) => (
#[allow(unused_variables)]
#[allow(unreachable_code)]
|arg|
{
match arg
{
$(
$($pat)|+ $(if $cond)? => Some($result)
),*,
_ => None,
}
}
);
}
#[macro_export]
#[doc(hidden)]
macro_rules! __is_defined_at_macro
{
($($($pat:pat_param)|+ $(if $cond:expr)? => $result:expr),*) => (
#[allow(unused_variables)]
|arg| -> bool
{
#[allow(unreachable_code)]
match arg
{
$(
$($pat)|+ $(if $cond)? => true
),*,
_ => false,
}
}
);
}
#[macro_export]
macro_rules! partial_fn {
($($($pat:pat_param)|+ $(if $cond:expr)* => $result:expr),*$(,)*) => (
PartialFn::new(
Box::new(__call_macro!($($($pat)|+ $(if $cond)* => $result),*)),
Box::new(__is_defined_at_macro!($($($pat)|+ $(if $cond)* => $result),*))
)
);
}