Skip to content

Commit

Permalink
Merge pull request #35 from epage/specialized
Browse files Browse the repository at this point in the history
 feat(str): Specialized string predicates
  • Loading branch information
epage authored May 10, 2018
2 parents 874b7c3 + e846b95 commit a3c8d61
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 54 deletions.
103 changes: 52 additions & 51 deletions src/set.rs → src/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,49 @@ use Predicate;
/// Note that this implementation places the fewest restrictions on the
/// underlying `Item` type at the expense of having the least performant
/// implementation (linear search). If the type to be searched is `Hash + Eq`,
/// it is much more efficient to use `HashableContainsPredicate` and
/// `contains_hashable`. The implementation-specific predicates will be
/// it is much more efficient to use `HashableInPredicate` and
/// `in_hash`. The implementation-specific predicates will be
/// deprecated when Rust supports trait specialization.
#[derive(Debug)]
pub struct ContainsPredicate<T>
pub struct InPredicate<T>
where
T: PartialEq,
{
inner: Vec<T>,
}

impl<T> Predicate<T> for ContainsPredicate<T>
impl<T> InPredicate<T>
where
T: Ord,
{
/// Creates a new predicate that will return `true` when the given `variable` is
/// contained with the set of items provided.
///
/// Note that this implementation requires `Item` to be `Ord`. The
/// `InPredicate` uses a less efficient search algorithm but only
/// requires `Item` implement `PartialEq`. The implementation-specific
/// predicates will be deprecated when Rust supports trait specialization.
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::in_iter(vec![1, 3, 5]).sort();
/// assert_eq!(true, predicate_fn.eval(&1));
/// assert_eq!(false, predicate_fn.eval(&2));
/// assert_eq!(true, predicate_fn.eval(&3));
/// assert_eq!(false, predicate_fn.eval(&4));
/// assert_eq!(true, predicate_fn.eval(&5));
/// ```
pub fn sort(self) -> OrdInPredicate<T> {
let mut items = self.inner;
items.sort();
OrdInPredicate { inner: items }
}
}

impl<T> Predicate<T> for InPredicate<T>
where
T: PartialEq,
{
Expand All @@ -46,28 +77,28 @@ where
/// Note that this implementation places the fewest restrictions on the
/// underlying `Item` type at the expense of having the least performant
/// implementation (linear search). If the type to be searched is `Hash + Eq`,
/// it is much more efficient to use `HashableContainsPredicate` and
/// `contains_hashable`. The implementation-specific predicates will be
/// it is much more efficient to use `HashableInPredicate` and
/// `in_hash`. The implementation-specific predicates will be
/// deprecated when Rust supports trait specialization.
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::contains(vec![1, 3, 5]);
/// let predicate_fn = predicate::in_iter(vec![1, 3, 5]);
/// assert_eq!(true, predicate_fn.eval(&1));
/// assert_eq!(false, predicate_fn.eval(&2));
/// assert_eq!(true, predicate_fn.eval(&3));
/// assert_eq!(false, predicate_fn.eval(&4));
/// assert_eq!(true, predicate_fn.eval(&5));
/// ```
pub fn contains<I, T>(iter: I) -> ContainsPredicate<T>
pub fn in_iter<I, T>(iter: I) -> InPredicate<T>
where
T: PartialEq,
I: IntoIterator<Item = T>,
{
ContainsPredicate {
InPredicate {
inner: Vec::from_iter(iter),
}
}
Expand All @@ -76,20 +107,20 @@ where
/// set, otherwise returns `false`.
///
/// Note that this implementation requires `Item` to be `Ord`. The
/// `ContainsPredicate` uses a less efficient search algorithm but only
/// `InPredicate` uses a less efficient search algorithm but only
/// requires `Item` implement `PartialEq`. The implementation-specific
/// predicates will be deprecated when Rust supports trait specialization.
///
/// This is created by the `predicate::contains_ord` function.
/// This is created by the `predicate::in_iter(...).sort` function.
#[derive(Debug)]
pub struct OrdContainsPredicate<T>
pub struct OrdInPredicate<T>
where
T: Ord,
{
inner: Vec<T>,
}

impl<T> Predicate<T> for OrdContainsPredicate<T>
impl<T> Predicate<T> for OrdInPredicate<T>
where
T: Ord,
{
Expand All @@ -98,54 +129,24 @@ where
}
}

/// Creates a new predicate that will return `true` when the given `variable` is
/// contained with the set of items provided.
///
/// Note that this implementation requires `Item` to be `Ord`. The
/// `ContainsPredicate` uses a less efficient search algorithm but only
/// requires `Item` implement `PartialEq`. The implementation-specific
/// predicates will be deprecated when Rust supports trait specialization.
///
/// # Examples
///
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::contains_ord(vec![1, 3, 5]);
/// assert_eq!(true, predicate_fn.eval(&1));
/// assert_eq!(false, predicate_fn.eval(&2));
/// assert_eq!(true, predicate_fn.eval(&3));
/// assert_eq!(false, predicate_fn.eval(&4));
/// assert_eq!(true, predicate_fn.eval(&5));
/// ```
pub fn contains_ord<I, T>(iter: I) -> OrdContainsPredicate<T>
where
T: Ord,
I: IntoIterator<Item = T>,
{
let mut items = Vec::from_iter(iter);
items.sort();
OrdContainsPredicate { inner: items }
}

/// Predicate that returns `true` if `variable` is a member of the pre-defined
/// `HashSet`, otherwise returns `false`.
///
/// Note that this implementation requires `Item` to be `Hash + Eq`. The
/// `ContainsPredicate` uses a less efficient search algorithm but only
/// `InPredicate` uses a less efficient search algorithm but only
/// requires `Item` implement `PartialEq`. The implementation-specific
/// predicates will be deprecated when Rust supports trait specialization.
///
/// This is created by the `predicate::contains_hashable` function.
/// This is created by the `predicate::in_hash` function.
#[derive(Debug)]
pub struct HashableContainsPredicate<T>
pub struct HashableInPredicate<T>
where
T: Hash + Eq,
{
inner: HashSet<T>,
}

impl<T> Predicate<T> for HashableContainsPredicate<T>
impl<T> Predicate<T> for HashableInPredicate<T>
where
T: Hash + Eq,
{
Expand All @@ -158,7 +159,7 @@ where
/// contained with the set of items provided.
///
/// Note that this implementation requires `Item` to be `Hash + Eq`. The
/// `ContainsPredicate` uses a less efficient search algorithm but only
/// `InPredicate` uses a less efficient search algorithm but only
/// requires `Item` implement `PartialEq`. The implementation-specific
/// predicates will be deprecated when Rust supports trait specialization.
///
Expand All @@ -167,19 +168,19 @@ where
/// ```
/// use predicates::prelude::*;
///
/// let predicate_fn = predicate::contains_hashable(vec![1, 3, 5]);
/// let predicate_fn = predicate::in_hash(vec![1, 3, 5]);
/// assert_eq!(true, predicate_fn.eval(&1));
/// assert_eq!(false, predicate_fn.eval(&2));
/// assert_eq!(true, predicate_fn.eval(&3));
/// assert_eq!(false, predicate_fn.eval(&4));
/// assert_eq!(true, predicate_fn.eval(&5));
/// ```
pub fn contains_hashable<I, T>(iter: I) -> HashableContainsPredicate<T>
pub fn in_hash<I, T>(iter: I) -> HashableInPredicate<T>
where
T: Hash + Eq,
I: IntoIterator<Item = T>,
{
HashableContainsPredicate {
HashableInPredicate {
inner: HashSet::from_iter(iter),
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
//! }
//!
//! assert_eq!(true, IsTheAnswer.eval(&42));
//! let almost_the_answer = IsTheAnswer.or(predicate::contains(vec![41, 43]));
//! let almost_the_answer = IsTheAnswer.or(predicate::in_iter(vec![41, 43]));
//! assert_eq!(true, almost_the_answer.eval(&41));
//!
//! // Any function over a reference to the desired `Item` that returns `bool`
Expand Down Expand Up @@ -102,7 +102,7 @@ pub use boxed::BoxPredicate;
pub mod constant;
pub mod function;
pub mod ord;
pub mod set;
pub mod iter;

// combinators
pub mod boolean;
Expand Down
5 changes: 4 additions & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ pub mod predicate {
pub use constant::{always, never};
pub use function::function;
pub use ord::{eq, ge, gt, le, lt, ne};
pub use set::{contains, contains_hashable, contains_ord};
pub use iter::{in_hash, in_iter};

/// `str` Predicate factories
///
/// This module contains predicates specific to string handling.
pub mod str {
pub use str::is_empty;
pub use str::{contains, ends_with, starts_with};

#[cfg(feature = "difference")]
pub use str::{diff, similar};

Expand Down
Loading

0 comments on commit a3c8d61

Please sign in to comment.