use super::combinators::Predicate;
use std::cmp::PartialOrd;
#[derive(Clone, Copy, Debug)]
pub struct Eq<T>(pub T);
impl<T: PartialEq + Send + Sync> Predicate<T> for Eq<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value == self.0
}
}
pub fn eq<T: PartialEq + Send + Sync>(value: T) -> Eq<T> {
Eq(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Ne<T>(pub T);
impl<T: PartialEq + Send + Sync> Predicate<T> for Ne<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value != self.0
}
}
pub fn ne<T: PartialEq + Send + Sync>(value: T) -> Ne<T> {
Ne(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Gt<T>(pub T);
impl<T: PartialOrd + Send + Sync> Predicate<T> for Gt<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value > self.0
}
}
pub fn gt<T: PartialOrd + Send + Sync>(value: T) -> Gt<T> {
Gt(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Ge<T>(pub T);
impl<T: PartialOrd + Send + Sync> Predicate<T> for Ge<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value >= self.0
}
}
pub fn ge<T: PartialOrd + Send + Sync>(value: T) -> Ge<T> {
Ge(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Lt<T>(pub T);
impl<T: PartialOrd + Send + Sync> Predicate<T> for Lt<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value < self.0
}
}
pub fn lt<T: PartialOrd + Send + Sync>(value: T) -> Lt<T> {
Lt(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Le<T>(pub T);
impl<T: PartialOrd + Send + Sync> Predicate<T> for Le<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value <= self.0
}
}
pub fn le<T: PartialOrd + Send + Sync>(value: T) -> Le<T> {
Le(value)
}
#[derive(Clone, Copy, Debug)]
pub struct Between<T> {
min: T,
max: T,
}
impl<T: PartialOrd + Send + Sync> Predicate<T> for Between<T> {
#[inline]
fn check(&self, value: &T) -> bool {
*value >= self.min && *value <= self.max
}
}
pub fn between<T: PartialOrd + Send + Sync>(min: T, max: T) -> Between<T> {
Between { min, max }
}
pub fn positive<T>() -> Gt<T>
where
T: PartialOrd + Default + Send + Sync,
{
Gt(T::default())
}
pub fn negative<T>() -> Lt<T>
where
T: PartialOrd + Default + Send + Sync,
{
Lt(T::default())
}
pub fn non_negative<T>() -> Ge<T>
where
T: PartialOrd + Default + Send + Sync,
{
Ge(T::default())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::predicate::PredicateExt;
#[test]
fn test_eq() {
assert!(eq(5).check(&5));
assert!(!eq(5).check(&4));
}
#[test]
fn test_ne() {
let p = ne(5);
assert!(p.check(&4));
assert!(p.check(&6));
assert!(!p.check(&5));
}
#[test]
fn test_gt() {
assert!(gt(5).check(&6));
assert!(!gt(5).check(&5));
assert!(!gt(5).check(&4));
}
#[test]
fn test_ge() {
assert!(ge(5).check(&6));
assert!(ge(5).check(&5));
assert!(!ge(5).check(&4));
}
#[test]
fn test_lt() {
assert!(lt(5).check(&4));
assert!(!lt(5).check(&5));
assert!(!lt(5).check(&6));
}
#[test]
fn test_le() {
assert!(le(5).check(&4));
assert!(le(5).check(&5));
assert!(!le(5).check(&6));
}
#[test]
fn test_between() {
let p = between(0, 100);
assert!(p.check(&0));
assert!(p.check(&50));
assert!(p.check(&100));
assert!(!p.check(&-1));
assert!(!p.check(&101));
}
#[test]
fn test_positive() {
let p = positive::<i32>();
assert!(p.check(&1));
assert!(!p.check(&0));
assert!(!p.check(&-1));
}
#[test]
fn test_negative() {
let p = negative::<i32>();
assert!(p.check(&-1));
assert!(!p.check(&0));
assert!(!p.check(&1));
}
#[test]
fn test_non_negative() {
let p = non_negative::<i32>();
assert!(p.check(&0));
assert!(p.check(&1));
assert!(!p.check(&-1));
}
#[test]
fn test_combined_number_predicates() {
let p = gt(10).and(lt(20));
assert!(p.check(&15));
assert!(!p.check(&10));
assert!(!p.check(&20));
assert!(!p.check(&5));
assert!(!p.check(&25));
}
#[test]
fn test_with_floats() {
let p = between(0.0_f64, 1.0_f64);
assert!(p.check(&0.5));
assert!(p.check(&0.0));
assert!(p.check(&1.0));
assert!(!p.check(&-0.1));
assert!(!p.check(&1.1));
}
}