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}