From 97b83fe851fe2448d6f90427e8ea0a965f5a7a49 Mon Sep 17 00:00:00 2001 From: Lee Bousfield Date: Tue, 23 Aug 2016 12:15:01 -0600 Subject: Implement Fn(I) -> bool for Filter structs --- src/impl_traits.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/impl_traits.rs (limited to 'src/impl_traits.rs') diff --git a/src/impl_traits.rs b/src/impl_traits.rs new file mode 100644 index 0000000..4d6c8cc --- /dev/null +++ b/src/impl_traits.rs @@ -0,0 +1,63 @@ +/// Creates operator implementations for a Filter struct +/// Currently only Fn and Filter implementations are handled +/// +/// Takes at least two arguments: the struct to implement the traits for, and +/// the block to define the filter function. Preceeding the block should be the +/// variables for self and the passed in argument to filter, separated by spaces. +/// After that, any filter generics needed for the struct should be specified. +/// +/// # Examples +/// +/// ``` +/// # #![cfg_attr(feature = "unstable-filter-as-fn", feature(unboxed_closures, fn_traits))] +/// # #[macro_use] extern crate filters; +/// # use filters::filter::Filter; +/// # fn main() { +/// struct Or { +/// a: T, +/// b: U +/// } +/// +/// impl_operators!(Or, self e { self.a.filter(e) || self.b.filter(e) }, T, U); +/// +/// let or = Or {a: |&x: &i32| x < 5, b: |&x: &i32| x > 10}; +/// assert_eq!(or.filter(&0), true); +/// assert_eq!(or.filter(&7), false); +/// assert_eq!(or.filter(&15), true); +/// // If unstable-filter-as-fn is enabled `or` will also be a Fn(&i32) -> bool +/// # } +/// ``` +#[macro_export] +macro_rules! impl_operators { + ($struct_ident:ident, $self_var: ident $arg_var: ident $filter_impl:block, $( $generic:ident ),*) => { + #[cfg(feature = "unstable-filter-as-fn")] + impl<'a, I, $( $generic: Filter, )*> FnOnce<(&'a I,)> for $struct_ident<$( $generic, )*> { + type Output = bool; + extern "rust-call" fn call_once<'b>(self, (arg,): (&'a I,)) -> Self::Output { + self.filter(arg) + } + } + + #[cfg(feature = "unstable-filter-as-fn")] + impl<'a, I, $( $generic: Filter, )*> FnMut<(&'a I,)> for $struct_ident<$( $generic, )*> { + extern "rust-call" fn call_mut<'b>(&mut self, (arg,): (&'a I,)) -> Self::Output { + self.filter(arg) + } + } + + #[cfg(feature = "unstable-filter-as-fn")] + impl<'a, I, $( $generic: Filter, )*> Fn<(&'a I,)> for $struct_ident<$( $generic, )*> { + #[allow(unused_variables)] + extern "rust-call" fn call<'b>(&$self_var, ($arg_var,): (&'a I,)) -> Self::Output $filter_impl + } + + #[cfg(not(feature = "unstable-filter-as-fn"))] + impl, )*> Filter for $struct_ident<$( $generic, )*> { + #[allow(unused_variables)] + fn filter(&$self_var, $arg_var: &I) -> bool $filter_impl + } + }; + ($struct_ident:ident, $self_var: ident $arg_var: ident $filter_impl: block) => { + impl_operators!($struct_ident, $self_var $arg_var $filter_impl, ); + }; +} -- cgit v1.2.3