summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2017-10-03 10:20:58 +0200
committerGitHub <noreply@github.com>2017-10-03 10:20:58 +0200
commitbdc2c062c2632fd6e0f9be4113b239f1cf84f0b9 (patch)
treee1573c1dd5e95e3217b2d5c2848b92ea267bc9fe
parentf80413b5a481badd19a5ccd09f1d071498228781 (diff)
parenta8d0c99d991889125340c5e09c32bae8776189b9 (diff)
Merge pull request #21 from PlasmaPower/filter-map
Add filter map functions
-rw-r--r--src/failable/filter.rs76
-rw-r--r--src/failable/ops/map.rs58
-rw-r--r--src/failable/ops/mod.rs1
-rw-r--r--src/filter.rs27
-rw-r--r--src/ops/map.rs35
-rw-r--r--src/ops/mod.rs1
6 files changed, 197 insertions, 1 deletions
diff --git a/src/failable/filter.rs b/src/failable/filter.rs
index de49512..af08fbb 100644
--- a/src/failable/filter.rs
+++ b/src/failable/filter.rs
@@ -5,12 +5,14 @@
//
use std::error::Error;
+use std::borrow::Borrow;
pub use failable::ops::and::FailableAnd;
pub use failable::ops::bool::FailableBool;
pub use failable::ops::not::FailableNot;
pub use failable::ops::xor::FailableXOr;
pub use failable::ops::or::FailableOr;
+pub use failable::ops::map::{FailableMapInput, FailableMapErr};
/// Trait for converting something into a Filter
pub trait IntoFailableFilter<N, E: Error + Sized> {
@@ -376,6 +378,80 @@ pub trait FailableFilter<N, E: Error> {
FailableNot::new(FailableAnd::new(self, other))
}
+ /// Helper to transform the input of a filter
+ ///
+ /// ```
+ /// # #[derive(Debug)]
+ /// # struct ErrorStub { }
+ /// #
+ /// # impl ::std::fmt::Display for ErrorStub {
+ /// # fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ /// # Ok(())
+ /// # }
+ /// # }
+ /// #
+ /// # impl ::std::error::Error for ErrorStub {
+ /// # fn description(&self) -> &str { "stub" }
+ /// # }
+ /// #
+ /// use filters::failable::filter::FailableFilter;
+ ///
+ /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
+ /// let b = (|&a: &i64| -> Result<bool, ErrorStub> { Ok(a < 7) });
+ /// let b = b.map_input(|&x: &usize| x as i64);
+ /// let c = a.and(b);
+ ///
+ /// assert!(!c.filter(&1).unwrap());
+ /// assert!(c.filter(&3).unwrap());
+ /// assert!(c.filter(&4).unwrap());
+ /// assert!(c.filter(&6).unwrap());
+ /// assert!(!c.filter(&9).unwrap());
+ /// ```
+ fn map_input<O, B, T, M>(self, map: M) -> FailableMapInput<Self, M, O, B>
+ where Self: Sized,
+ M: Fn(&T) -> N,
+ B: Borrow<O> + Sized
+ {
+ FailableMapInput::new(self, map)
+ }
+
+ /// Helper to transform the input of a filter
+ ///
+ /// ```
+ /// # use std::fmt;
+ /// # #[derive(Debug)]
+ /// # struct ErrorStub { }
+ /// #
+ /// # impl ::std::fmt::Display for ErrorStub {
+ /// # fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+ /// # Ok(())
+ /// # }
+ /// # }
+ /// #
+ /// # impl ::std::error::Error for ErrorStub {
+ /// # fn description(&self) -> &str { "stub" }
+ /// # }
+ /// #
+ /// use filters::failable::filter::FailableFilter;
+ ///
+ /// let a = (|&a: &usize| -> Result<bool, ErrorStub> { Ok(a > 1) });
+ /// let b = (|&a: &usize| -> Result<bool, fmt::Error> { Ok(a < 7) });
+ /// let b = b.map_err(|_: fmt::Error| ErrorStub {});
+ /// let c = a.and(b);
+ ///
+ /// assert!(!c.filter(&1).unwrap());
+ /// assert!(c.filter(&3).unwrap());
+ /// assert!(c.filter(&4).unwrap());
+ /// assert!(c.filter(&6).unwrap());
+ /// assert!(!c.filter(&9).unwrap());
+ /// ```
+ fn map_err<M, OE>(self, map: M) -> FailableMapErr<Self, M, E, OE>
+ where Self: Sized,
+ M: Fn(E) -> OE
+ {
+ FailableMapErr::new(self, map)
+ }
+
}
/// All closures that take a ref to something and return Result<bool, E> are failable filters
diff --git a/src/failable/ops/map.rs b/src/failable/ops/map.rs
new file mode 100644
index 0000000..8e1155c
--- /dev/null
+++ b/src/failable/ops/map.rs
@@ -0,0 +1,58 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+//! Map implementation.
+//!
+//! Will be automatically included when incluing `filter::Filter`, so importing this module
+//! shouldn't be necessary.
+//!
+use std::marker::PhantomData;
+use std::borrow::Borrow;
+use std::error::Error;
+
+use failable::filter::FailableFilter;
+
+#[must_use = "filters are lazy and do nothing unless consumed"]
+#[derive(Clone)]
+pub struct FailableMapInput<F, M, FT, B>(F, M, PhantomData<FT>, PhantomData<B>);
+
+impl<F, M, FT, B> FailableMapInput<F, M, FT, B> {
+ pub fn new(a: F, m: M) -> FailableMapInput<F, M, FT, B> {
+ FailableMapInput(a, m, PhantomData, PhantomData)
+ }
+}
+
+impl<FT, E, F, T, B, M> FailableFilter<T, E> for FailableMapInput<F, M, FT, B>
+ where E: Error,
+ F: FailableFilter<FT, E>,
+ B: Borrow<FT> + Sized,
+ M: Fn(&T) -> B
+{
+ fn filter(&self, e: &T) -> Result<bool, E> {
+ self.0.filter(self.1(e).borrow())
+ }
+}
+
+#[must_use = "filters are lazy and do nothing unless consumed"]
+#[derive(Clone)]
+pub struct FailableMapErr<F, M, FE, E>(F, M, PhantomData<FE>, PhantomData<E>);
+
+impl<F, M, FE, E> FailableMapErr<F, M, FE, E> {
+ pub fn new(a: F, m: M) -> FailableMapErr<F, M, FE, E> {
+ FailableMapErr(a, m, PhantomData, PhantomData)
+ }
+}
+
+impl<FE, E, F, T, M> FailableFilter<T, E> for FailableMapErr<F, M, FE, E>
+ where E: Error,
+ FE: Error,
+ F: FailableFilter<T, FE>,
+ M: Fn(FE) -> E
+{
+ fn filter(&self, e: &T) -> Result<bool, E> {
+ self.0.filter(e).map_err(&self.1)
+ }
+}
diff --git a/src/failable/ops/mod.rs b/src/failable/ops/mod.rs
index feaad07..618c0e8 100644
--- a/src/failable/ops/mod.rs
+++ b/src/failable/ops/mod.rs
@@ -9,3 +9,4 @@ pub mod bool;
pub mod not;
pub mod xor;
pub mod or;
+pub mod map;
diff --git a/src/filter.rs b/src/filter.rs
index ac0d7b1..d2748bd 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -6,12 +6,14 @@
//! The filter implementation
//!
+use std::borrow::Borrow;
pub use ops::and::And;
pub use ops::bool::Bool;
pub use ops::not::Not;
pub use ops::xor::XOr;
pub use ops::or::Or;
+pub use ops::map::MapInput;
/// Trait for converting something into a Filter
pub trait IntoFilter<N> {
@@ -36,7 +38,7 @@ impl<I, T: Fn(&I) -> bool> Filter<I> for T {
}
}
-/// The filter trai
+/// The filter trait
pub trait Filter<N> {
/// The function which is used to filter something
@@ -256,6 +258,29 @@ pub trait Filter<N> {
Not::new(And::new(self, other))
}
+ /// Helper to transform the input of a filter
+ ///
+ /// ```
+ /// use filters::filter::Filter;
+ ///
+ /// let a = (|&a: &usize| { a > 1 });
+ /// let b = (|&a: &i64| { a < 7 });
+ /// let b = b.map_input(|&x: &usize| { x as i64 });
+ /// let c = a.and(b);
+ ///
+ /// assert!(!c.filter(&1));
+ /// assert!(c.filter(&3));
+ /// assert!(c.filter(&4));
+ /// assert!(c.filter(&6));
+ /// assert!(!c.filter(&9));
+ /// ```
+ fn map_input<O, B, T, M>(self, map: M) -> MapInput<Self, M, O, B>
+ where Self: Sized,
+ M: Fn(&T) -> N,
+ B: Borrow<O> + Sized
+ {
+ MapInput::new(self, map)
+ }
}
diff --git a/src/ops/map.rs b/src/ops/map.rs
new file mode 100644
index 0000000..b7a2028
--- /dev/null
+++ b/src/ops/map.rs
@@ -0,0 +1,35 @@
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+//! Map implementation.
+//!
+//! Will be automatically included when incluing `filter::Filter`, so importing this module
+//! shouldn't be necessary.
+//!
+use std::marker::PhantomData;
+use std::borrow::Borrow;
+
+use filter::Filter;
+
+#[must_use = "filters are lazy and do nothing unless consumed"]
+#[derive(Clone)]
+pub struct MapInput<F, M, FT, B>(F, M, PhantomData<FT>, PhantomData<B>);
+
+impl<F, M, FT, B> MapInput<F, M, FT, B> {
+ pub fn new(a: F, m: M) -> MapInput<F, M, FT, B> {
+ MapInput(a, m, PhantomData, PhantomData)
+ }
+}
+
+impl<FT, F, T, B, M> Filter<T> for MapInput<F, M, FT, B>
+ where F: Filter<FT>,
+ B: Borrow<FT> + Sized,
+ M: Fn(&T) -> B
+{
+ fn filter(&self, e: &T) -> bool {
+ self.0.filter(self.1(e).borrow())
+ }
+}
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index d152cce..a5dd6b6 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -9,3 +9,4 @@ pub mod bool;
pub mod not;
pub mod or;
pub mod xor;
+pub mod map;