Skip to main content

rust_rule_engine/
lib.rs

1//! # Rust Rule Engine v1.20.0 - Performance Optimization Release
2//!
3//! A high-performance rule engine for Rust with **RETE-UL algorithm**, **Array Membership (`in`) operator**,
4//! **String Methods (startsWith, endsWith)**, **Plugin System**, and **GRL (Grule Rule Language)** support.
5//! Features forward/backward chaining, stream processing, and production-ready performance.
6//!
7//! ## What's New in v1.20.0
8//!
9//! - **⚡ Zero-Copy String Operations**: New `Value::as_string_ref()` reduces allocations in hot paths by 2x
10//! - **🚀 Optimized Rule Iteration**: Index-based rule access eliminates `get_rules().clone()` overhead (41-683x faster)
11//! - **💾 Memory Efficiency**: `Facts::with_value()` callback API reduces cloning by 40% in rule evaluation
12//! - **📊 RETE Performance**: `FactValue::as_str()` with `Cow<str>` optimizes comparison and hashing
13//! - **🔬 Comprehensive Benchmarks**: New `clone_optimization_benchmark` measures all optimized paths
14//! - **✅ Zero Breaking Changes**: All 443 tests passing, backward compatible API additions only
15//!
16//! ### Performance Improvements
17//!
18//! This release focuses on eliminating unnecessary `.clone()` calls in critical execution paths:
19//!
20//! - **String Operators**: `Contains`, `StartsWith`, `EndsWith`, `Matches` now use zero-copy references
21//! - **KnowledgeBase Operations**: Rule counting and lookup operations are 100-600x faster
22//! - **Facts Access**: New callback-based API avoids cloning values during rule evaluation
23//! - **RETE Memoization**: Optimized fact hashing reduces memory allocations by 60%
24//!
25//! Fixed critical unwraps in:
26//! - Date parsing (`.and_hms_opt()` now properly propagates errors)
27//! - String operations (`find`, `strip_prefix` use safe patterns)
28//! - Iterator operations (clear invariant documentation)
29//! - Character access (handles empty strings gracefully)
30//!
31//! ```rust
32//! // Before v1.19.3 - Could panic
33//! // naive_date.and_hms_opt(0, 0, 0).unwrap()
34//!
35//! // v1.19.3 - Returns Result with helpful error message
36//! use rust_rule_engine::parser::grl::GRLParser;
37//!
38//! let result = GRLParser::parse_rules("malformed GRL...");
39//! match result {
40//!     Ok(rules) => println!("Parsed {} rules", rules.len()),
41//!     Err(e) => println!("Parse error: {}", e), // Descriptive message, no panic
42//! }
43//! ```
44//!
45//! ## Features
46//!
47//! - **🔌 Plugin System**: Modular plugin architecture with lifecycle management
48//! - **🛠️ Built-in Plugin Suite**: 44+ actions & 33+ functions for common operations  
49//! - **🔥 GRL Support**: Full Grule-compatible syntax
50//! - **🎯 Method Calls**: `$Object.method(args)` and property access
51//! - **📊 Knowledge Base**: Centralized rule management with salience
52//! - **💾 Working Memory**: Facts system for complex object interactions
53//! - **⚡ High Performance**: Optimized execution with cycle detection
54//! - **🔄 Arithmetic**: Complex calculations in conditions and actions
55//! - **🛡️ Type Safety**: Rust's type system ensures runtime safety
56//!
57//! ## Quick Start with Plugins
58//!
59//! ```rust
60//! use rust_rule_engine::*;
61//!
62//! fn main() -> Result<()> {
63//!     // Create Knowledge Base and Engine
64//!     let kb = KnowledgeBase::new("Demo");
65//!     let mut engine = RustRuleEngine::new(kb);
66//!     let mut facts = Facts::new();
67//!     
68//!     // Set up data
69//!     facts.set("user.age", Value::Number(25.0));
70//!     facts.set("user.premium", Value::Boolean(false));
71//!     
72//!     // Define GRL rule
73//!     let rule = r#"
74//!     rule "PremiumUpgrade" salience 10 {
75//!         when
76//!             user.age >= 18 && user.premium == false
77//!         then
78//!             user.premium = true;
79//!             user.discount = 0.1;
80//!     }
81//!     "#;
82//!     
83//!     // Parse and add rule to knowledge base
84//!     let rules = GRLParser::parse_rules(rule)?;
85//!     for r in rules {
86//!         engine.knowledge_base().add_rule(r)?;
87//!     }
88//!     
89//!     // Execute with facts
90//!     let result = engine.execute(&facts)?;
91//!     println!("User premium status: {:?}", facts.get("user.premium"));
92//!     
93//!     Ok(())
94//! }
95//! ```
96//!
97//! Built-in Plugin Suite provides comprehensive functionality for common operations:
98//!
99//! - **String Utilities**: 8 actions, 5 functions for text manipulation
100//! - **Math Operations**: 10 actions, 6 functions for calculations  
101//! - **Date/Time**: 8 actions, 7 functions for temporal operations
102//! - Actions: CurrentDate, CurrentTime, FormatDate, ParseDate, AddDays, AddHours, DateDiff, IsWeekend
103//! - Functions: now, today, dayOfWeek, dayOfYear, year, month, day
104//!
105//! ### Validation (8 actions, 6 functions)
106//! - Actions: ValidateEmail, ValidatePhone, ValidateUrl, ValidateRegex, ValidateRange, ValidateLength, ValidateNotEmpty, ValidateNumeric
107//! - Functions: isEmail, isPhone, isUrl, isNumeric, isEmpty, inRange
108//!
109//! ### Collections (10 actions, 9 functions)
110//! - Actions: ArrayLength, ArrayPush, ArrayPop, ArraySort, ArrayFilter, ArrayMap, ArrayFind, ObjectKeys, ObjectValues, ObjectMerge
111//! - Functions: length, contains, first, last, reverse, join, slice, keys, values
112//!
113//!   // Create engine
114//!   let mut engine = RustRuleEngine::new(kb);
115//!
116//!   // Create facts
117//!   let facts = Facts::new();
118//!   let user = FactHelper::create_user("john", 25, "john@email.com", "US", false);
119//!   facts.add_value("User", user)?;
120//!
121//!   // Execute rules
122//!   let result = engine.execute(&facts)?;
123//!   println!("Rules fired: {}", result.rules_fired);
124//!
125//!   Ok(())
126//!   }
127//! ```
128
129#![warn(missing_docs)]
130#![warn(clippy::all)]
131
132/// Backward chaining (goal-driven reasoning) - requires 'backward-chaining' feature
133#[cfg(feature = "backward-chaining")]
134#[allow(missing_docs)]
135pub mod backward;
136/// Rule execution engine and related components
137#[allow(missing_docs)]
138pub mod engine;
139/// Error types and result handling
140pub mod errors;
141/// Expression evaluation (arithmetic operations)
142#[allow(missing_docs)]
143pub mod expression;
144/// Rule parsing and language support
145#[allow(missing_docs)]
146pub mod parser;
147/// Built-in plugin system for extended functionality
148#[allow(missing_docs)]
149pub mod plugins;
150/// RETE module for rule evaluation
151#[allow(missing_docs)]
152pub mod rete;
153/// Streaming rule engine for real-time event processing
154#[cfg(feature = "streaming")]
155#[allow(missing_docs)]
156pub mod streaming;
157/// Core type definitions for values, operators, and actions
158pub mod types;
159
160// Re-export core types for easy access
161pub use errors::{Result, RuleEngineError};
162pub use types::{ActionType, LogicalOperator, Operator, Value};
163
164// Re-export Grule-style components
165pub use engine::engine::{EngineConfig, GruleExecutionResult, RustRuleEngine};
166pub use engine::facts::{FactHelper, Facts};
167pub use engine::knowledge_base::KnowledgeBase;
168pub use engine::rule::{Condition, ConditionGroup, Rule};
169
170// Re-export parsers
171pub use parser::grl::GRLParser;
172
173/// Builder pattern for creating a RustRuleEngine with various configurations.
174///
175/// Provides a fluent interface for configuring and building rule engines with
176/// rules loaded from files or inline GRL strings.
177///
178/// # Examples
179///
180/// ```rust
181/// use rust_rule_engine::RuleEngineBuilder;
182///
183/// // Build engine with inline rules
184/// let engine = RuleEngineBuilder::new()
185///     .with_inline_grl(r#"
186///         rule "VIP Check" {
187///             when user.points > 1000
188///             then user.vip = true;
189///         }
190///     "#)?
191///     .build();
192/// # Ok::<(), Box<dyn std::error::Error>>(())
193/// ```
194pub struct RuleEngineBuilder {
195    kb: KnowledgeBase,
196    config: EngineConfig,
197}
198
199impl RuleEngineBuilder {
200    /// Create a new RuleEngineBuilder with default configuration.
201    ///
202    /// Creates an empty knowledge base named "DefaultKB" and default engine configuration.
203    pub fn new() -> Self {
204        Self {
205            kb: KnowledgeBase::new("DefaultKB"),
206            config: EngineConfig::default(),
207        }
208    }
209
210    /// Add rules from a .grl file.
211    ///
212    /// Reads and parses GRL rules from the specified file path.
213    ///
214    /// # Errors
215    ///
216    /// Returns an error if the file cannot be read or if the GRL syntax is invalid.
217    pub fn with_rule_file<P: AsRef<std::path::Path>>(self, path: P) -> Result<Self> {
218        let content = std::fs::read_to_string(path)?;
219        let rules = GRLParser::parse_rules(&content)?;
220
221        for rule in rules {
222            self.kb.add_rule(rule)?;
223        }
224
225        Ok(self)
226    }
227
228    /// Add rules from inline GRL string.
229    ///
230    /// Parses GRL rules directly from a string.
231    ///
232    /// # Errors
233    ///
234    /// Returns an error if the GRL syntax is invalid.
235    pub fn with_inline_grl(self, grl_content: &str) -> Result<Self> {
236        let rules = GRLParser::parse_rules(grl_content)?;
237
238        for rule in rules {
239            self.kb.add_rule(rule)?;
240        }
241
242        Ok(self)
243    }
244
245    /// Set engine configuration.
246    ///
247    /// Overrides the default engine configuration with custom settings.
248    pub fn with_config(mut self, config: EngineConfig) -> Self {
249        self.config = config;
250        self
251    }
252
253    /// Build the RustRuleEngine.
254    ///
255    /// Consumes the builder and creates a configured rule engine instance.
256    pub fn build(self) -> RustRuleEngine {
257        RustRuleEngine::with_config(self.kb, self.config)
258    }
259}
260
261impl Default for RuleEngineBuilder {
262    fn default() -> Self {
263        Self::new()
264    }
265}