mintyml 0.1.19

A minialist alternative syntax to HTML
Documentation
use core::ops::{BitAnd, BitOr, Not};

use super::{
    super::{DirectionPrecedence, InferencePredicate, InferencePredicateContext, TestResult},
    when, InferWhen,
};

pub struct AndPredicate<P1, P2> {
    pred1: P1,
    pred2: P2,
}

pub struct OrPredicate<P1, P2> {
    pred1: P1,
    pred2: P2,
}

pub struct NotPredicate<P> {
    pred: P,
}

impl<P1, P2> BitAnd<InferWhen<P2>> for InferWhen<P1>
where
    P1: InferencePredicate,
    P2: InferencePredicate,
{
    type Output = InferWhen<AndPredicate<P1, P2>>;

    fn bitand(self, rhs: InferWhen<P2>) -> Self::Output {
        when(AndPredicate {
            pred1: self.0,
            pred2: rhs.0,
        })
    }
}

impl<P1, P2> BitOr<InferWhen<P2>> for InferWhen<P1>
where
    P1: InferencePredicate,
    P2: InferencePredicate,
{
    type Output = InferWhen<OrPredicate<P1, P2>>;

    fn bitor(self, rhs: InferWhen<P2>) -> Self::Output {
        when(OrPredicate {
            pred1: self.0,
            pred2: rhs.0,
        })
    }
}

impl<P> Not for InferWhen<P>
where
    P: InferencePredicate,
{
    type Output = InferWhen<NotPredicate<P>>;

    fn not(self) -> Self::Output {
        when(NotPredicate { pred: self.0 })
    }
}

impl<P1, P2> InferencePredicate for AndPredicate<P1, P2>
where
    P1: InferencePredicate,
    P2: InferencePredicate,
{
    fn test(&mut self, cx: &InferencePredicateContext) -> TestResult {
        match self.pred1.test(cx) {
            Ok(false) => return Ok(false),
            res => res,
        }
        .and(match self.pred2.test(cx) {
            Ok(false) => return Ok(false),
            res => res,
        })
    }

    fn direction_precedence(&self) -> DirectionPrecedence {
        self.pred1.direction_precedence() + self.pred2.direction_precedence()
    }
}

impl<P1, P2> InferencePredicate for OrPredicate<P1, P2>
where
    P1: InferencePredicate,
    P2: InferencePredicate,
{
    fn test(&mut self, cx: &InferencePredicateContext) -> TestResult {
        match self.pred1.test(cx) {
            Ok(true) => return Ok(true),
            res => res,
        }
        .and(match self.pred2.test(cx) {
            Ok(true) => return Ok(true),
            res => res,
        })
    }

    fn direction_precedence(&self) -> DirectionPrecedence {
        self.pred1.direction_precedence() + self.pred2.direction_precedence()
    }
}

impl<P> InferencePredicate for NotPredicate<P>
where
    P: InferencePredicate,
{
    fn test(&mut self, cx: &InferencePredicateContext) -> TestResult {
        self.pred.test(cx).map(Not::not)
    }

    fn direction_precedence(&self) -> DirectionPrecedence {
        self.pred.direction_precedence()
    }
}