vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
// Typed rule conditions and formula trees.

use crate::ops::rule::builder;
use crate::ir::Program;


/// A typed rule leaf condition.
///
/// `pattern_id` indexes the `rule_bitmaps` and `rule_counts` buffers used by
/// [`RuleFormula::to_program`]. File-size thresholds are accepted as `u64`;
/// thresholds above the current scalar IR file-size range are folded to their
/// mathematically forced result.
///
/// # Examples
///
/// ```
/// use vyre::ops::rule::RuleCondition;
///
/// let condition = RuleCondition::PatternCountGte {
///     pattern_id: 7,
///     threshold: 2,
/// };
/// assert!(matches!(condition, RuleCondition::PatternCountGte { .. }));
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RuleCondition {
    /// True when the pattern has any match state.
    PatternExists {
        /// Pattern table index.
        pattern_id: u32,
    },
    /// True when the pattern count is strictly greater than `threshold`.
    PatternCountGt {
        /// Pattern table index.
        pattern_id: u32,
        /// Exclusive lower bound.
        threshold: u32,
    },
    /// True when the pattern count is greater than or equal to `threshold`.
    PatternCountGte {
        /// Pattern table index.
        pattern_id: u32,
        /// Inclusive lower bound.
        threshold: u32,
    },
    /// True when the file size is less than the threshold.
    FileSizeLt(u64),
    /// True when the file size is less than or equal to the threshold.
    FileSizeLte(u64),
    /// True when the file size is greater than the threshold.
    FileSizeGt(u64),
    /// True when the file size is greater than or equal to the threshold.
    FileSizeGte(u64),
    /// True when the file size equals the threshold.
    FileSizeEq(u64),
    /// True when the file size does not equal the threshold.
    FileSizeNe(u64),
    /// Constant true leaf.
    LiteralTrue,
    /// Constant false leaf.
    LiteralFalse,
}


/// A typed boolean rule formula tree.
///
/// Formula nodes compose typed conditions directly. They are not serialized
/// through an instruction stream and they do not require a runtime reducer.
///
/// # Examples
///
/// ```
/// use vyre::ops::rule::{RuleCondition, RuleFormula};
///
/// let formula = RuleFormula::and(
///     RuleFormula::condition(RuleCondition::PatternExists { pattern_id: 0 }),
///     RuleFormula::not(RuleFormula::condition(RuleCondition::LiteralFalse)),
/// );
/// let program = formula.to_program();
/// assert!(program.has_buffer("verdicts"));
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RuleFormula {
    /// Leaf condition.
    Condition(RuleCondition),
    /// Logical conjunction.
    And(Box<RuleFormula>, Box<RuleFormula>),
    /// Logical disjunction.
    Or(Box<RuleFormula>, Box<RuleFormula>),
    /// Logical negation.
    Not(Box<RuleFormula>),
}


impl RuleFormula {
    /// Create a leaf formula.
    #[must_use]
    pub fn condition(condition: RuleCondition) -> Self {
        Self::Condition(condition)
    }

    /// Create a conjunction.
    #[must_use]
    pub fn and(left: Self, right: Self) -> Self {
        Self::And(Box::new(left), Box::new(right))
    }

    /// Create a disjunction.
    #[must_use]
    pub fn or(left: Self, right: Self) -> Self {
        Self::Or(Box::new(left), Box::new(right))
    }

    /// Create a negation.
    #[must_use]
    pub fn not_formula(formula: Self) -> Self {
        Self::Not(Box::new(formula))
    }

    /// Create a negation.
    #[must_use]
    pub fn not(formula: Self) -> Self {
        Self::not_formula(formula)
    }

    /// Build a one-rule [`Program`] that stores the formula verdict at index 0.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::rule::{RuleCondition, RuleFormula};
    ///
    /// let program = RuleFormula::condition(RuleCondition::LiteralTrue).to_program();
    /// assert!(program.has_buffer("rule_bitmaps"));
    /// assert!(program.has_buffer("verdicts"));
    /// ```
    #[must_use]
    pub fn to_program(&self) -> Program {
        builder::build_rule_program(&[(self.clone(), 0)])
    }
}