use super::field_predicate::FieldPredicate;
use std::ops::{BitAnd, BitOr, BitXor, Not};
#[derive(Debug)]
#[non_exhaustive]
pub enum BasicPredicate<T> {
True,
False,
Field(FieldPredicate<T>),
And(Vec<BasicPredicate<T>>),
Or(Vec<BasicPredicate<T>>),
Not(Box<BasicPredicate<T>>),
Xor(Box<BasicPredicate<T>>, Box<BasicPredicate<T>>),
}
impl<T> Clone for BasicPredicate<T> {
fn clone(&self) -> Self {
match self {
Self::True => Self::True,
Self::False => Self::False,
Self::Field(field) => Self::Field(field.clone()),
Self::And(parts) => Self::And(parts.clone()),
Self::Or(parts) => Self::Or(parts.clone()),
Self::Not(inner) => Self::Not(Box::new((**inner).clone())),
Self::Xor(left, right) => {
Self::Xor(Box::new((**left).clone()), Box::new((**right).clone()))
}
}
}
}
pub trait IntoBasicPredicate<T> {
fn into_basic_predicate(self) -> BasicPredicate<T>;
}
impl<T> IntoBasicPredicate<T> for BasicPredicate<T> {
fn into_basic_predicate(self) -> BasicPredicate<T> {
self
}
}
impl<T> BasicPredicate<T> {
pub fn evaluate(&self, value: &T) -> bool {
match self {
Self::True => true,
Self::False => false,
Self::Field(fp) => fp.evaluate(value),
Self::And(children) => children.iter().all(|c| c.evaluate(value)),
Self::Or(children) => children.iter().any(|c| c.evaluate(value)),
Self::Not(inner) => !inner.evaluate(value),
Self::Xor(a, b) => a.evaluate(value) ^ b.evaluate(value),
}
}
}
impl<T> BitAnd for BasicPredicate<T> {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
match (self, rhs) {
(Self::And(mut l), Self::And(r)) => {
l.extend(r);
Self::And(l)
}
(Self::And(mut l), r) => {
l.push(r);
Self::And(l)
}
(l, Self::And(mut r)) => {
r.insert(0, l);
Self::And(r)
}
(l, r) => Self::And(vec![l, r]),
}
}
}
impl<T> BitOr for BasicPredicate<T> {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
match (self, rhs) {
(Self::Or(mut l), Self::Or(r)) => {
l.extend(r);
Self::Or(l)
}
(Self::Or(mut l), r) => {
l.push(r);
Self::Or(l)
}
(l, Self::Or(mut r)) => {
r.insert(0, l);
Self::Or(r)
}
(l, r) => Self::Or(vec![l, r]),
}
}
}
impl<T> BitXor for BasicPredicate<T> {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
Self::Xor(Box::new(self), Box::new(rhs))
}
}
impl<T> Not for BasicPredicate<T> {
type Output = Self;
fn not(self) -> Self {
match self {
Self::Not(inner) => *inner, Self::True => Self::False,
Self::False => Self::True,
other => Self::Not(Box::new(other)),
}
}
}