use std::fmt;
use std::marker::PhantomData;
use crate::reflection;
use crate::Predicate;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AndPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
a: M1,
b: M2,
_phantom: PhantomData<Item>,
}
impl<M1, M2, Item> AndPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
pub fn new(a: M1, b: M2) -> AndPredicate<M1, M2, Item> {
AndPredicate {
a,
b,
_phantom: PhantomData,
}
}
}
impl<M1, M2, Item> Predicate<Item> for AndPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn eval(&self, item: &Item) -> bool {
self.a.eval(item) && self.b.eval(item)
}
fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
let child_a = self.a.find_case(expected, variable);
match (expected, child_a) {
(true, Some(child_a)) => self.b.find_case(expected, variable).map(|child_b| {
reflection::Case::new(Some(self), expected)
.add_child(child_a)
.add_child(child_b)
}),
(true, None) => None,
(false, Some(child_a)) => {
Some(reflection::Case::new(Some(self), expected).add_child(child_a))
}
(false, None) => self
.b
.find_case(expected, variable)
.map(|child_b| reflection::Case::new(Some(self), expected).add_child(child_b)),
}
}
}
impl<M1, M2, Item> reflection::PredicateReflection for AndPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![
reflection::Child::new("left", &self.a),
reflection::Child::new("right", &self.b),
];
Box::new(params.into_iter())
}
}
impl<M1, M2, Item> fmt::Display for AndPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({} && {})", self.a, self.b)
}
}
#[cfg(test)]
mod test_and {
use crate::prelude::*;
#[test]
fn find_case_true() {
assert!(predicate::always()
.and(predicate::always())
.find_case(true, &5)
.is_some());
}
#[test]
fn find_case_true_left_fail() {
assert!(predicate::never()
.and(predicate::always())
.find_case(true, &5)
.is_none());
}
#[test]
fn find_case_true_right_fail() {
assert!(predicate::always()
.and(predicate::never())
.find_case(true, &5)
.is_none());
}
#[test]
fn find_case_true_fails() {
assert!(predicate::never()
.and(predicate::never())
.find_case(true, &5)
.is_none());
}
#[test]
fn find_case_false() {
assert!(predicate::never()
.and(predicate::never())
.find_case(false, &5)
.is_some());
}
#[test]
fn find_case_false_fails() {
assert!(predicate::always()
.and(predicate::always())
.find_case(false, &5)
.is_none());
}
#[test]
fn find_case_false_left_fail() {
assert!(predicate::never()
.and(predicate::always())
.find_case(false, &5)
.is_some());
}
#[test]
fn find_case_false_right_fail() {
assert!(predicate::always()
.and(predicate::never())
.find_case(false, &5)
.is_some());
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct OrPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
a: M1,
b: M2,
_phantom: PhantomData<Item>,
}
impl<M1, M2, Item> OrPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
pub fn new(a: M1, b: M2) -> OrPredicate<M1, M2, Item> {
OrPredicate {
a,
b,
_phantom: PhantomData,
}
}
}
impl<M1, M2, Item> Predicate<Item> for OrPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn eval(&self, item: &Item) -> bool {
self.a.eval(item) || self.b.eval(item)
}
fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
let child_a = self.a.find_case(expected, variable);
match (expected, child_a) {
(true, Some(child_a)) => {
Some(reflection::Case::new(Some(self), expected).add_child(child_a))
}
(true, None) => self
.b
.find_case(expected, variable)
.map(|child_b| reflection::Case::new(Some(self), expected).add_child(child_b)),
(false, Some(child_a)) => self.b.find_case(expected, variable).map(|child_b| {
reflection::Case::new(Some(self), expected)
.add_child(child_a)
.add_child(child_b)
}),
(false, None) => None,
}
}
}
impl<M1, M2, Item> reflection::PredicateReflection for OrPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![
reflection::Child::new("left", &self.a),
reflection::Child::new("right", &self.b),
];
Box::new(params.into_iter())
}
}
impl<M1, M2, Item> fmt::Display for OrPredicate<M1, M2, Item>
where
M1: Predicate<Item>,
M2: Predicate<Item>,
Item: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({} || {})", self.a, self.b)
}
}
#[cfg(test)]
mod test_or {
use crate::prelude::*;
#[test]
fn find_case_true() {
assert!(predicate::always()
.or(predicate::always())
.find_case(true, &5)
.is_some());
}
#[test]
fn find_case_true_left_fail() {
assert!(predicate::never()
.or(predicate::always())
.find_case(true, &5)
.is_some());
}
#[test]
fn find_case_true_right_fail() {
assert!(predicate::always()
.or(predicate::never())
.find_case(true, &5)
.is_some());
}
#[test]
fn find_case_true_fails() {
assert!(predicate::never()
.or(predicate::never())
.find_case(true, &5)
.is_none());
}
#[test]
fn find_case_false() {
assert!(predicate::never()
.or(predicate::never())
.find_case(false, &5)
.is_some());
}
#[test]
fn find_case_false_fails() {
assert!(predicate::always()
.or(predicate::always())
.find_case(false, &5)
.is_none());
}
#[test]
fn find_case_false_left_fail() {
assert!(predicate::never()
.or(predicate::always())
.find_case(false, &5)
.is_none());
}
#[test]
fn find_case_false_right_fail() {
assert!(predicate::always()
.or(predicate::never())
.find_case(false, &5)
.is_none());
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NotPredicate<M, Item>
where
M: Predicate<Item>,
Item: ?Sized,
{
inner: M,
_phantom: PhantomData<Item>,
}
impl<M, Item> NotPredicate<M, Item>
where
M: Predicate<Item>,
Item: ?Sized,
{
pub fn new(inner: M) -> NotPredicate<M, Item> {
NotPredicate {
inner,
_phantom: PhantomData,
}
}
}
impl<M, Item> Predicate<Item> for NotPredicate<M, Item>
where
M: Predicate<Item>,
Item: ?Sized,
{
fn eval(&self, item: &Item) -> bool {
!self.inner.eval(item)
}
fn find_case<'a>(&'a self, expected: bool, variable: &Item) -> Option<reflection::Case<'a>> {
self.inner
.find_case(!expected, variable)
.map(|child| reflection::Case::new(Some(self), expected).add_child(child))
}
}
impl<M, Item> reflection::PredicateReflection for NotPredicate<M, Item>
where
M: Predicate<Item>,
Item: ?Sized,
{
fn children<'a>(&'a self) -> Box<dyn Iterator<Item = reflection::Child<'a>> + 'a> {
let params = vec![reflection::Child::new("predicate", &self.inner)];
Box::new(params.into_iter())
}
}
impl<M, Item> fmt::Display for NotPredicate<M, Item>
where
M: Predicate<Item>,
Item: ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(! {})", self.inner)
}
}
pub trait PredicateBooleanExt<Item: ?Sized>
where
Self: Predicate<Item>,
{
fn and<B>(self, other: B) -> AndPredicate<Self, B, Item>
where
B: Predicate<Item>,
Self: Sized,
{
AndPredicate::new(self, other)
}
fn or<B>(self, other: B) -> OrPredicate<Self, B, Item>
where
B: Predicate<Item>,
Self: Sized,
{
OrPredicate::new(self, other)
}
fn not(self) -> NotPredicate<Self, Item>
where
Self: Sized,
{
NotPredicate::new(self)
}
}
impl<P, Item> PredicateBooleanExt<Item> for P
where
P: Predicate<Item>,
Item: ?Sized,
{
}