pub enum Value {
String(String),
Number(f64),
Integer(i64),
Boolean(bool),
Array(Vec<Value>),
Object(HashMap<String, Value>),
Null,
}Expand description
Represents a value that can be used in rule conditions and actions
Variants§
String(String)
String value
Number(f64)
Floating point number
Integer(i64)
Integer value
Boolean(bool)
Boolean value
Array(Vec<Value>)
Array of values
Object(HashMap<String, Value>)
Object with key-value pairs
Null
Null value
Implementations§
Source§impl Value
impl Value
Sourcepub fn to_string(&self) -> String
pub fn to_string(&self) -> String
Convert Value to string representation
Examples found in repository?
examples/rule_file_functions_demo.rs (line 84)
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10 println!("🎯 Custom Functions from Rule File Demo");
11 println!("=======================================\n");
12
13 // Read rules from file
14 let rule_file_path = "examples/rules/car_functions.grl";
15 println!("📄 Reading rules from file: {}", rule_file_path);
16
17 let rule_content = fs::read_to_string(rule_file_path)
18 .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20 println!("📋 Rule file content:");
21 println!("---");
22 println!("{}", rule_content);
23 println!("---\n");
24
25 // Create facts
26 let facts = Facts::new();
27
28 // Car data - set speed > 80 to trigger speed limit rule
29 let mut car_props = HashMap::new();
30 car_props.insert("Speed".to_string(), Value::Number(95.0)); // Above speed limit
31 car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
32 car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
33 car_props.insert("IsRunning".to_string(), Value::Boolean(true));
34
35 // Driver data
36 let mut driver_props = HashMap::new();
37 driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
38 driver_props.insert("Experience".to_string(), Value::Integer(7)); // Experienced driver
39 driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
40
41 facts.add_value("Car", Value::Object(car_props))?;
42 facts.add_value("Driver", Value::Object(driver_props))?;
43
44 println!("🏁 Initial state:");
45 if let Some(car) = facts.get("Car") {
46 println!(" Car = {car:?}");
47 }
48 if let Some(driver) = facts.get("Driver") {
49 println!(" Driver = {driver:?}");
50 }
51 println!();
52
53 // Create knowledge base
54 let mut kb = KnowledgeBase::new("RuleFileDemo");
55
56 // Parse GRL file and add rules to knowledge base
57 println!("🔧 Parsing GRL file content...");
58 let parsed_rules = SimpleGRLParser::parse_rules(&rule_content)
59 .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
60
61 println!(
62 "✅ Successfully parsed {} rules from file",
63 parsed_rules.len()
64 );
65 for rule in parsed_rules {
66 println!(" 📋 Rule: {} (salience: {})", rule.name, rule.salience);
67 let _ = kb.add_rule(rule);
68 }
69 println!();
70
71 // Create engine
72 let config = EngineConfig {
73 debug_mode: true,
74 max_cycles: 3,
75 ..Default::default()
76 };
77 let mut engine = RustRuleEngine::with_config(kb, config);
78
79 // Register all custom functions called from the rule file
80 println!("📝 Registering custom functions from rule file...");
81
82 // Functions from SpeedLimitCheck rule
83 engine.register_function("checkSpeedLimit", |args, facts| {
84 let speed_field = args.get(0).unwrap().to_string();
85 let limit = args.get(1).unwrap();
86
87 let speed = if let Some(car) = facts.get("Car") {
88 if let Value::Object(obj) = car {
89 obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
90 } else {
91 Value::Number(0.0)
92 }
93 } else {
94 Value::Number(0.0)
95 };
96
97 let result = format!("🚦 Speed check: {:?} vs limit {:?}", speed, limit);
98 println!("{}", result);
99 Ok(Value::String(result))
100 });
101
102 engine.register_function("sendAlert", |args, facts| {
103 let message = args.get(0).unwrap().to_string();
104 let driver_field = args.get(1).unwrap().to_string();
105
106 let driver_name = if let Some(driver) = facts.get("Driver") {
107 if let Value::Object(obj) = driver {
108 obj.get("Name")
109 .cloned()
110 .unwrap_or(Value::String("Unknown".to_string()))
111 } else {
112 Value::String("Unknown".to_string())
113 }
114 } else {
115 Value::String("Unknown".to_string())
116 };
117
118 let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
119 println!("{}", alert);
120 Ok(Value::String(alert))
121 });
122
123 // Functions from DriverValidation rule
124 engine.register_function("validateDriver", |args, _facts| {
125 let name_field = args.get(0).unwrap().to_string();
126 let exp_field = args.get(1).unwrap().to_string();
127
128 let result = format!(
129 "✅ Driver validation: {} (experience: {})",
130 name_field, exp_field
131 );
132 println!("{}", result);
133 Ok(Value::String(result))
134 });
135
136 engine.register_function("calculateInsurance", |args, _facts| {
137 let exp_field = args.get(0).unwrap().to_string();
138 let engine_field = args.get(1).unwrap().to_string();
139
140 let result = format!(
141 "💰 Insurance: Experience {} + Engine {} = Premium",
142 exp_field, engine_field
143 );
144 println!("{}", result);
145 Ok(Value::String(result))
146 });
147
148 // Functions from EngineDiagnostics rule
149 engine.register_function("performDiagnostics", |args, _facts| {
150 let engine_field = args.get(0).unwrap().to_string();
151 let speed_field = args.get(1).unwrap().to_string();
152
153 let result = format!(
154 "🔧 Diagnostics: Engine {} at speed {} - OK",
155 engine_field, speed_field
156 );
157 println!("{}", result);
158 Ok(Value::String(result))
159 });
160
161 engine.register_function("optimizePerformance", |args, _facts| {
162 let current_speed = args.get(0).unwrap().to_string();
163 let max_speed = args.get(1).unwrap().to_string();
164
165 let result = format!(
166 "⚡ Performance: {} / {} - Optimized",
167 current_speed, max_speed
168 );
169 println!("{}", result);
170 Ok(Value::String(result))
171 });
172
173 // Functions from MaintenanceCheck rule
174 engine.register_function("scheduleMaintenanceCheck", |args, _facts| {
175 let engine_field = args.get(0).unwrap().to_string();
176 let exp_field = args.get(1).unwrap().to_string();
177
178 let result = format!(
179 "🔧 Maintenance scheduled: Engine {} (driver exp: {})",
180 engine_field, exp_field
181 );
182 println!("{}", result);
183 Ok(Value::String(result))
184 });
185
186 engine.register_function("updateMaintenanceRecord", |args, _facts| {
187 let name_field = args.get(0).unwrap().to_string();
188 let engine_field = args.get(1).unwrap().to_string();
189
190 let result = format!("📋 Record updated: {} - {}", name_field, engine_field);
191 println!("{}", result);
192 Ok(Value::String(result))
193 });
194
195 println!("✅ Registered {} custom functions from rule file:", 8);
196 println!(" 🚦 checkSpeedLimit");
197 println!(" 🚨 sendAlert");
198 println!(" ✅ validateDriver");
199 println!(" 💰 calculateInsurance");
200 println!(" 🔧 performDiagnostics");
201 println!(" ⚡ optimizePerformance");
202 println!(" 🔧 scheduleMaintenanceCheck");
203 println!(" 📋 updateMaintenanceRecord");
204 println!();
205
206 // Execute rules
207 println!("🚀 Executing rules from file...");
208 let result = engine.execute(&facts)?;
209
210 println!("\n📊 Rule File Execution Results:");
211 println!(" Cycles: {}", result.cycle_count);
212 println!(" Rules evaluated: {}", result.rules_evaluated);
213 println!(" Rules fired: {}", result.rules_fired);
214 println!(" Execution time: {:?}", result.execution_time);
215
216 println!("\n🏁 Final state:");
217 if let Some(car) = facts.get("Car") {
218 println!(" Car = {car:?}");
219 }
220 if let Some(driver) = facts.get("Driver") {
221 println!(" Driver = {driver:?}");
222 }
223
224 println!("\n🎯 Rule File Custom Functions Demonstrated:");
225 println!(" 📄 Rules defined in external .grl file");
226 println!(" 📞 Custom functions called from rule file");
227 println!(" 🔧 Business logic separated from rule definitions");
228 println!(" 📋 File-based rule management");
229 println!(" ⚡ Function registry with rule file integration");
230
231 Ok(())
232}More examples
examples/custom_functions_demo.rs (line 139)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("🎯 Custom Function Calls Demo");
10 println!("=============================\n");
11
12 // Create facts
13 let facts = Facts::new();
14
15 // Car data
16 let mut car_props = HashMap::new();
17 car_props.insert("Speed".to_string(), Value::Number(60.0));
18 car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
19 car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
20 car_props.insert("IsRunning".to_string(), Value::Boolean(true));
21
22 // Driver data
23 let mut driver_props = HashMap::new();
24 driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
25 driver_props.insert("Experience".to_string(), Value::Integer(5));
26 driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
27
28 facts.add_value("Car", Value::Object(car_props))?;
29 facts.add_value("Driver", Value::Object(driver_props))?;
30
31 println!("🏁 Initial state:");
32 if let Some(car) = facts.get("Car") {
33 println!(" Car = {car:?}");
34 }
35 if let Some(driver) = facts.get("Driver") {
36 println!(" Driver = {driver:?}");
37 }
38 println!();
39
40 // Create knowledge base
41 let mut kb = KnowledgeBase::new("CustomFunctionRules");
42
43 // Rule 1: Speed Check with custom function
44 let speed_check_rule = Rule::new(
45 "SpeedCheck".to_string(),
46 ConditionGroup::single(Condition::new(
47 "Car.Speed".to_string(),
48 Operator::GreaterThan,
49 Value::Number(80.0),
50 )),
51 vec![
52 ActionType::Call {
53 function: "checkSpeedLimit".to_string(),
54 args: vec![Value::String("Car.Speed".to_string()), Value::Number(80.0)],
55 },
56 ActionType::Call {
57 function: "sendAlert".to_string(),
58 args: vec![
59 Value::String("Speed limit exceeded!".to_string()),
60 Value::String("Driver.Name".to_string()),
61 ],
62 },
63 ],
64 )
65 .with_salience(20);
66
67 // Rule 2: Driver validation
68 let driver_validation_rule = Rule::new(
69 "DriverValidation".to_string(),
70 ConditionGroup::single(Condition::new(
71 "Driver.License".to_string(),
72 Operator::Equal,
73 Value::String("VALID".to_string()),
74 )),
75 vec![
76 ActionType::Call {
77 function: "validateDriver".to_string(),
78 args: vec![
79 Value::String("Driver.Name".to_string()),
80 Value::String("Driver.Experience".to_string()),
81 ],
82 },
83 ActionType::Call {
84 function: "calculateInsurance".to_string(),
85 args: vec![
86 Value::String("Driver.Experience".to_string()),
87 Value::String("Car.Engine".to_string()),
88 ],
89 },
90 ],
91 )
92 .with_salience(15);
93
94 // Rule 3: Engine diagnostics
95 let engine_diagnostics_rule = Rule::new(
96 "EngineDiagnostics".to_string(),
97 ConditionGroup::single(Condition::new(
98 "Car.IsRunning".to_string(),
99 Operator::Equal,
100 Value::Boolean(true),
101 )),
102 vec![
103 ActionType::Call {
104 function: "performDiagnostics".to_string(),
105 args: vec![
106 Value::String("Car.Engine".to_string()),
107 Value::String("Car.Speed".to_string()),
108 ],
109 },
110 ActionType::Call {
111 function: "optimizePerformance".to_string(),
112 args: vec![
113 Value::String("Car.Speed".to_string()),
114 Value::String("Car.MaxSpeed".to_string()),
115 ],
116 },
117 ],
118 )
119 .with_salience(10);
120
121 // Add rules to knowledge base
122 let _ = kb.add_rule(speed_check_rule);
123 let _ = kb.add_rule(driver_validation_rule);
124 let _ = kb.add_rule(engine_diagnostics_rule);
125
126 // Create engine
127 let config = EngineConfig {
128 debug_mode: true,
129 max_cycles: 3,
130 ..Default::default()
131 };
132 let mut engine = RustRuleEngine::with_config(kb, config);
133
134 // Register custom functions
135 println!("📝 Registering custom functions...");
136
137 // Function 1: Check speed limit
138 engine.register_function("checkSpeedLimit", |args, facts| {
139 let speed_field = args.get(0).unwrap().to_string();
140 let limit = args.get(1).unwrap();
141
142 // Get actual speed value from facts
143 let speed = if let Some(car) = facts.get("Car") {
144 if let Value::Object(obj) = car {
145 obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
146 } else {
147 Value::Number(0.0)
148 }
149 } else {
150 Value::Number(0.0)
151 };
152
153 let result = format!("Speed check: {:?} vs limit {:?}", speed, limit);
154 println!("🚦 {}", result);
155 Ok(Value::String(result))
156 });
157
158 // Function 2: Send alert
159 engine.register_function("sendAlert", |args, facts| {
160 let message = args.get(0).unwrap().to_string();
161 let driver_field = args.get(1).unwrap().to_string();
162
163 // Get driver name from facts
164 let driver_name = if let Some(driver) = facts.get("Driver") {
165 if let Value::Object(obj) = driver {
166 obj.get("Name")
167 .cloned()
168 .unwrap_or(Value::String("Unknown".to_string()))
169 } else {
170 Value::String("Unknown".to_string())
171 }
172 } else {
173 Value::String("Unknown".to_string())
174 };
175
176 let alert = format!("🚨 ALERT to {:?}: {}", driver_name, message);
177 println!("{}", alert);
178 Ok(Value::String(alert))
179 });
180
181 // Function 3: Validate driver
182 engine.register_function("validateDriver", |args, _facts| {
183 let name_field = args.get(0).unwrap().to_string();
184 let exp_field = args.get(1).unwrap().to_string();
185
186 let result = format!(
187 "✅ Driver validation passed for {} (experience: {})",
188 name_field, exp_field
189 );
190 println!("{}", result);
191 Ok(Value::String(result))
192 });
193
194 // Function 4: Calculate insurance
195 engine.register_function("calculateInsurance", |args, _facts| {
196 let exp_field = args.get(0).unwrap().to_string();
197 let engine_field = args.get(1).unwrap().to_string();
198
199 let result = format!(
200 "💰 Insurance calculated: Experience {} + Engine {} = Premium rate",
201 exp_field, engine_field
202 );
203 println!("{}", result);
204 Ok(Value::String(result))
205 });
206
207 // Function 5: Perform diagnostics
208 engine.register_function("performDiagnostics", |args, _facts| {
209 let engine_field = args.get(0).unwrap().to_string();
210 let speed_field = args.get(1).unwrap().to_string();
211
212 let result = format!(
213 "🔧 Diagnostics: Engine {} running at speed {} - All systems OK",
214 engine_field, speed_field
215 );
216 println!("{}", result);
217 Ok(Value::String(result))
218 });
219
220 // Function 6: Optimize performance
221 engine.register_function("optimizePerformance", |args, _facts| {
222 let current_speed = args.get(0).unwrap().to_string();
223 let max_speed = args.get(1).unwrap().to_string();
224
225 let result = format!(
226 "⚡ Performance optimization: Current {} / Max {} - Efficiency tuned",
227 current_speed, max_speed
228 );
229 println!("{}", result);
230 Ok(Value::String(result))
231 });
232
233 println!("✅ Registered {} custom functions:", 6);
234 println!(" 🚦 checkSpeedLimit - Check if speed exceeds limit");
235 println!(" 🚨 sendAlert - Send alert message to driver");
236 println!(" ✅ validateDriver - Validate driver credentials");
237 println!(" 💰 calculateInsurance - Calculate insurance premium");
238 println!(" 🔧 performDiagnostics - Run engine diagnostics");
239 println!(" ⚡ optimizePerformance - Optimize engine performance");
240 println!();
241
242 // Execute rules
243 println!("🚀 Executing rules with custom functions...");
244 let result = engine.execute(&facts)?;
245
246 println!("\n📊 Custom Function Execution Results:");
247 println!(" Cycles: {}", result.cycle_count);
248 println!(" Rules evaluated: {}", result.rules_evaluated);
249 println!(" Rules fired: {}", result.rules_fired);
250 println!(" Execution time: {:?}", result.execution_time);
251
252 println!("\n🏁 Final state:");
253 if let Some(car) = facts.get("Car") {
254 println!(" Car = {car:?}");
255 }
256 if let Some(driver) = facts.get("Driver") {
257 println!(" Driver = {driver:?}");
258 }
259
260 println!("\n🎯 Custom Function Calls Demonstrated:");
261 println!(" 📞 User-defined functions called from rules");
262 println!(" 🔧 Custom business logic execution");
263 println!(" 🎪 Function registry system");
264 println!(" 📋 Rule-based custom function invocation");
265 println!(" ⚡ Real-time function parameter resolution");
266
267 Ok(())
268}examples/inline_rules_demo.rs (line 123)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("🎯 Inline GRL Rules Demo");
10 println!("========================\n");
11
12 // Define rules directly in code as strings
13 let grl_rules = r#"
14 rule "HighValueCustomer" salience 20 {
15 when
16 Customer.TotalSpent > 1000.0
17 then
18 sendWelcomeEmail(Customer.Email, "GOLD");
19 Customer.setTier("GOLD");
20 log("Customer upgraded to GOLD tier");
21 }
22
23 rule "LoyaltyBonus" salience 15 {
24 when
25 Customer.OrderCount >= 10
26 then
27 applyLoyaltyBonus(Customer.Id, 50.0);
28 Customer.setLoyaltyBonusApplied(true);
29 log("Loyalty bonus applied");
30 }
31
32 rule "NewCustomerWelcome" salience 10 {
33 when
34 Customer.IsNew == false && Customer.WelcomeEmailSent == false
35 then
36 sendWelcomeEmail(Customer.Email, "EXISTING");
37 Customer.setWelcomeEmailSent(true);
38 log("Welcome email sent to existing customer");
39 }
40
41 rule "LowRiskTransaction" salience 5 {
42 when
43 Transaction.Amount < 1000.0 && Transaction.RiskProcessed == false
44 then
45 Transaction.setRiskProcessed(true);
46 log("Low-risk transaction processed");
47 }
48 "#;
49
50 println!("📋 Inline GRL Rules:");
51 println!("---");
52 println!("{}", grl_rules.trim());
53 println!("---\n");
54
55 // Create facts
56 let facts = Facts::new();
57
58 // Customer data
59 let mut customer_props = HashMap::new();
60 customer_props.insert("Id".to_string(), Value::String("CUST001".to_string()));
61 customer_props.insert(
62 "Email".to_string(),
63 Value::String("john.doe@example.com".to_string()),
64 );
65 customer_props.insert("TotalSpent".to_string(), Value::Number(1250.0)); // Qualifies for GOLD
66 customer_props.insert("YearsActive".to_string(), Value::Integer(4)); // Long-time customer
67 customer_props.insert("OrderCount".to_string(), Value::Integer(12)); // Qualifies for loyalty
68 customer_props.insert("Tier".to_string(), Value::String("SILVER".to_string()));
69 customer_props.insert("IsNew".to_string(), Value::Boolean(false));
70 customer_props.insert("RiskScore".to_string(), Value::Integer(35)); // Low risk
71 customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
72 customer_props.insert("LoyaltyBonusApplied".to_string(), Value::Boolean(false));
73
74 // Transaction data
75 let mut transaction_props = HashMap::new();
76 transaction_props.insert("Id".to_string(), Value::String("TXN001".to_string()));
77 transaction_props.insert("Amount".to_string(), Value::Number(750.0)); // Normal amount
78 transaction_props.insert("Currency".to_string(), Value::String("USD".to_string()));
79 transaction_props.insert("RiskProcessed".to_string(), Value::Boolean(false));
80
81 facts.add_value("Customer", Value::Object(customer_props))?;
82 facts.add_value("Transaction", Value::Object(transaction_props))?;
83
84 println!("🏁 Initial state:");
85 if let Some(customer) = facts.get("Customer") {
86 println!(" Customer = {customer:?}");
87 }
88 if let Some(transaction) = facts.get("Transaction") {
89 println!(" Transaction = {transaction:?}");
90 }
91 println!();
92
93 // Create knowledge base and parse inline rules
94 let kb = KnowledgeBase::new("InlineRulesDemo");
95
96 println!("🔧 Parsing inline GRL rules...");
97 let parsed_rules = GRLParser::parse_rules(grl_rules)
98 .map_err(|e| format!("Failed to parse inline GRL rules: {:?}", e))?;
99
100 println!(
101 "✅ Successfully parsed {} rules from inline strings",
102 parsed_rules.len()
103 );
104 for rule in parsed_rules {
105 println!(" 📋 Rule: {} (salience: {})", rule.name, rule.salience);
106 let _ = kb.add_rule(rule);
107 }
108 println!();
109
110 // Create engine with configuration
111 let config = EngineConfig {
112 debug_mode: true,
113 max_cycles: 1, // PREVENT INFINITE LOOPS by limiting to 1 cycle
114 ..Default::default()
115 };
116 let mut engine = RustRuleEngine::with_config(kb, config);
117
118 // Register custom functions called from the inline rules
119 println!("📝 Registering custom functions for inline rules...");
120
121 // Customer tier management
122 engine.register_function("Customer.setTier", |args, facts| {
123 let new_tier = args.get(0).unwrap().to_string();
124
125 // ACTUALLY UPDATE THE FACTS in memory
126 facts
127 .set_nested("Customer.Tier", Value::String(new_tier.clone()))
128 .unwrap();
129
130 let result = format!("🏆 Customer tier updated to: {}", new_tier);
131 println!(" {}", result);
132 Ok(Value::String(result))
133 });
134
135 // Loyalty bonus management
136 engine.register_function("Customer.setLoyaltyBonusApplied", |args, facts| {
137 let applied = args.get(0).unwrap();
138
139 // ACTUALLY UPDATE THE FACTS in memory
140 facts
141 .set_nested("Customer.LoyaltyBonusApplied", applied.clone())
142 .unwrap();
143
144 let result = format!("🎯 Loyalty bonus status updated: {:?}", applied);
145 println!(" {}", result);
146 Ok(Value::String(result))
147 });
148
149 // Email service
150 engine.register_function("sendWelcomeEmail", |args, _facts| {
151 let email = args.get(0).unwrap().to_string();
152 let tier = args.get(1).unwrap().to_string();
153
154 let result = format!("📧 Welcome email sent to {} for {} tier", email, tier);
155 println!(" {}", result);
156 Ok(Value::String(result))
157 });
158
159 // Loyalty system
160 engine.register_function("applyLoyaltyBonus", |args, _facts| {
161 let customer_id = args.get(0).unwrap().to_string();
162 let bonus_amount = args.get(1).unwrap();
163
164 let result = format!(
165 "💰 Loyalty bonus of {:?} applied to customer {}",
166 bonus_amount, customer_id
167 );
168 println!(" {}", result);
169 Ok(Value::String(result))
170 });
171
172 // Security functions
173 engine.register_function("flagForReview", |args, _facts| {
174 let transaction_id = args.get(0).unwrap().to_string();
175
176 let result = format!(
177 "🚨 Transaction {} flagged for manual review",
178 transaction_id
179 );
180 println!(" {}", result);
181 Ok(Value::String(result))
182 });
183
184 engine.register_function("notifySecurityTeam", |args, _facts| {
185 let customer_id = args.get(0).unwrap().to_string();
186 let amount = args.get(1).unwrap();
187
188 let result = format!(
189 "🔒 Security team notified: Customer {} - Amount {:?}",
190 customer_id, amount
191 );
192 println!(" {}", result);
193 Ok(Value::String(result))
194 });
195
196 // Customer status updates
197 engine.register_function("Customer.setWelcomeEmailSent", |args, facts| {
198 let sent = args.get(0).unwrap();
199
200 // ACTUALLY UPDATE THE FACTS in memory
201 facts
202 .set_nested("Customer.WelcomeEmailSent", sent.clone())
203 .unwrap();
204
205 let result = format!("✅ Welcome email status updated: {:?}", sent);
206 println!(" {}", result);
207 Ok(Value::String(result))
208 });
209
210 // Transaction status updates
211 engine.register_function("Transaction.setRiskProcessed", |args, facts| {
212 let processed = args.get(0).unwrap();
213
214 // ACTUALLY UPDATE THE FACTS in memory
215 facts
216 .set_nested("Transaction.RiskProcessed", processed.clone())
217 .unwrap();
218
219 let result = format!("✅ Transaction risk processing completed: {:?}", processed);
220 println!(" {}", result);
221 Ok(Value::String(result))
222 });
223
224 println!("✅ Registered 8 custom functions for inline rules:");
225 println!(" 🏆 Customer.setTier");
226 println!(" 🎯 Customer.setLoyaltyBonusApplied");
227 println!(" 📧 sendWelcomeEmail");
228 println!(" 💰 applyLoyaltyBonus");
229 println!(" 🚨 flagForReview");
230 println!(" 🔒 notifySecurityTeam");
231 println!(" ✅ Customer.setWelcomeEmailSent");
232 println!(" ✅ Transaction.setRiskProcessed");
233 println!();
234
235 // Execute the inline rules
236 println!("🚀 Executing inline GRL rules...");
237 let result = engine.execute(&facts)?;
238
239 println!("\n📊 Inline Rules Execution Results:");
240 println!(" Cycles: {}", result.cycle_count);
241 println!(" Rules evaluated: {}", result.rules_evaluated);
242 println!(" Rules fired: {}", result.rules_fired);
243 println!(" Execution time: {:?}", result.execution_time);
244
245 println!("\n🏁 Final state:");
246 if let Some(customer) = facts.get("Customer") {
247 println!(" Customer = {customer:?}");
248 }
249 if let Some(transaction) = facts.get("Transaction") {
250 println!(" Transaction = {transaction:?}");
251 }
252
253 println!("\n🎯 Inline GRL Rules Demonstrated:");
254 println!(" 📝 Rules defined as strings directly in code");
255 println!(" 🔧 No external files needed");
256 println!(" ⚡ Quick prototyping and testing");
257 println!(" 🏆 Customer tier management");
258 println!(" 💰 Loyalty bonus system");
259 println!(" 🔒 Security and fraud detection");
260 println!(" 📧 Email notification system");
261
262 Ok(())
263}Sourcepub fn to_number(&self) -> Option<f64>
pub fn to_number(&self) -> Option<f64>
Convert Value to number if possible
Examples found in repository?
examples/advanced_method_calls.rs (line 81)
9fn demo_method_calls() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Advanced Method Calls ===");
11
12 // Create Knowledge Base
13 let kb = KnowledgeBase::new("MethodCallsDemo");
14
15 // Define rule with simpler condition first
16 let speedup_rule = r#"rule "SpeedUp" salience 10 {
17 when TestCar.speedUp == true
18 then TestCar.Speed = 70;
19 }"#;
20
21 // Parse and add rule
22 let rules = GRLParser::parse_rules(speedup_rule)?;
23 let rule = rules.into_iter().next().unwrap();
24 let _ = kb.add_rule(rule);
25
26 // Create engine with debug mode
27 let config = EngineConfig {
28 max_cycles: 10,
29 timeout: None,
30 enable_stats: true,
31 debug_mode: true,
32 };
33 let engine = RustRuleEngine::with_config(kb, config);
34
35 // Create facts
36 let facts = Facts::new();
37
38 // Create TestCar object using helper
39 let test_car = FactHelper::create_test_car(
40 true, // speedUp
41 50.0, // speed
42 100.0, // maxSpeed
43 10.0, // speedIncrement
44 );
45
46 // Create DistanceRecord object using helper
47 let distance_record = FactHelper::create_distance_record(0.0);
48
49 // Add facts
50 facts.add_value("TestCar", test_car)?;
51 facts.add_value("DistanceRecord", distance_record)?;
52
53 println!("\n🏁 Initial state:");
54 if let Some(car) = facts.get("TestCar") {
55 if let Some(speed) = car.get_property("Speed") {
56 println!(" TestCar.Speed = {:?}", speed);
57 }
58 if let Some(speed_up) = car.get_property("speedUp") {
59 println!(" TestCar.speedUp = {:?}", speed_up);
60 }
61 }
62
63 // Execute rules multiple cycles to see progression
64 println!("\n🚀 Executing SpeedUp rule multiple times...");
65 for i in 1..=3 {
66 println!("\n--- Cycle {} ---", i);
67 let result = engine.execute(&facts)?;
68
69 println!("Rules fired: {}", result.rules_fired);
70
71 if let Some(car) = facts.get("TestCar") {
72 if let Some(speed) = car.get_property("Speed") {
73 println!("TestCar.Speed after cycle {}: {:?}", i, speed);
74 }
75 }
76
77 // Check if we reached max speed
78 if let Some(car) = facts.get("TestCar") {
79 if let Some(speed) = car.get_property("speed") {
80 if let Some(max_speed) = car.get_property("maxSpeed") {
81 if speed.to_number() >= max_speed.to_number() {
82 println!("🏁 Max speed reached!");
83 break;
84 }
85 }
86 }
87 }
88 }
89
90 println!("\n📊 Final Results:");
91 if let Some(car) = facts.get("TestCar") {
92 if let Some(speed) = car.get_property("Speed") {
93 println!(" Final TestCar.Speed = {:?}", speed);
94 }
95 }
96
97 Ok(())
98}More examples
examples/complete_speedup_demo.rs (line 123)
9fn demo_complete_speedup_rule() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Complete SpeedUp Rule with Method Calls ===");
11 println!("Implementing the exact rule from the requirement:");
12 println!("rule \"SpeedUp\" salience 10");
13 println!("when");
14 println!(" $TestCar : TestCarClass( speedUp == true && speed < maxSpeed )");
15 println!(" $DistanceRecord : DistanceRecordClass()");
16 println!("then");
17 println!(" $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement);");
18 println!(" update($TestCar);");
19 println!(" $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed);");
20 println!(" update($DistanceRecord);");
21 println!("end\n");
22
23 // Create Knowledge Base
24 let kb = KnowledgeBase::new("SpeedUpDemo");
25
26 // For now, we'll use a simplified version that works with our current parser
27 let speedup_rule = r#"rule "SpeedUp" salience 10 {
28 when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed
29 then $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement); update($TestCar); $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed); update($DistanceRecord);
30 }"#;
31
32 // Parse and add rule
33 let rules = GRLParser::parse_rules(speedup_rule)?;
34 let rule = rules.into_iter().next().unwrap();
35 let _ = kb.add_rule(rule);
36
37 // Create engine with debug mode
38 let config = EngineConfig {
39 max_cycles: 10,
40 timeout: None,
41 enable_stats: true,
42 debug_mode: true,
43 };
44 let engine = RustRuleEngine::with_config(kb, config);
45
46 // Create facts
47 let facts = Facts::new();
48
49 // Create TestCar object - initial speed less than max
50 let test_car = FactHelper::create_test_car(
51 true, // speedUp
52 30.0, // speed (less than maxSpeed)
53 100.0, // maxSpeed
54 15.0, // speedIncrement
55 );
56
57 // Create DistanceRecord object
58 let distance_record = FactHelper::create_distance_record(0.0);
59
60 // Add facts
61 facts.add_value("TestCar", test_car)?;
62 facts.add_value("DistanceRecord", distance_record)?;
63
64 println!("🏁 Initial state:");
65 if let Some(car) = facts.get("TestCar") {
66 println!(
67 " TestCar.speed = {:?}",
68 car.get_property("speed").unwrap_or(Value::Null)
69 );
70 println!(
71 " TestCar.Speed = {:?}",
72 car.get_property("Speed").unwrap_or(Value::Null)
73 );
74 println!(
75 " TestCar.maxSpeed = {:?}",
76 car.get_property("maxSpeed").unwrap_or(Value::Null)
77 );
78 println!(
79 " TestCar.speedUp = {:?}",
80 car.get_property("speedUp").unwrap_or(Value::Null)
81 );
82 println!(
83 " TestCar.SpeedIncrement = {:?}",
84 car.get_property("SpeedIncrement").unwrap_or(Value::Null)
85 );
86 }
87 if let Some(record) = facts.get("DistanceRecord") {
88 println!(
89 " DistanceRecord.TotalDistance = {:?}",
90 record.get_property("TotalDistance").unwrap_or(Value::Null)
91 );
92 }
93
94 // Execute rules multiple cycles
95 println!("\n🚀 Executing SpeedUp rule...");
96 for i in 1..=5 {
97 println!("\n--- Cycle {} ---", i);
98 let result = engine.execute(&facts)?;
99
100 println!("Rules fired: {}", result.rules_fired);
101
102 if let Some(car) = facts.get("TestCar") {
103 println!(
104 "TestCar.Speed = {:?}",
105 car.get_property("Speed").unwrap_or(Value::Null)
106 );
107 println!(
108 "TestCar.speed = {:?}",
109 car.get_property("speed").unwrap_or(Value::Null)
110 );
111 }
112 if let Some(record) = facts.get("DistanceRecord") {
113 println!(
114 "DistanceRecord.TotalDistance = {:?}",
115 record.get_property("TotalDistance").unwrap_or(Value::Null)
116 );
117 }
118
119 // Check if we reached max speed
120 if let Some(car) = facts.get("TestCar") {
121 if let Some(speed) = car.get_property("speed") {
122 if let Some(max_speed) = car.get_property("maxSpeed") {
123 if speed.to_number() >= max_speed.to_number() {
124 println!("🏁 Max speed reached! Rule will no longer fire.");
125 break;
126 }
127 }
128 }
129 }
130
131 if result.rules_fired == 0 {
132 println!("ℹ️ No rules fired this cycle.");
133 break;
134 }
135 }
136
137 println!("\n📊 Final Summary:");
138 println!("✅ Successfully demonstrated method calls in GRL:");
139 println!(" • Method calls: $Object.method(args)");
140 println!(" • Property access: $Object.Property");
141 println!(" • Arithmetic expressions: $A.prop + $B.prop");
142 println!(" • update() function calls");
143 println!(" • Complex conditions with && operator");
144
145 Ok(())
146}Sourcepub fn as_integer(&self) -> Option<i64>
pub fn as_integer(&self) -> Option<i64>
Get integer value if this is an integer
Sourcepub fn as_boolean(&self) -> Option<bool>
pub fn as_boolean(&self) -> Option<bool>
Get boolean value if this is a boolean
Sourcepub fn call_method(
&mut self,
method: &str,
args: Vec<Value>,
) -> Result<Value, String>
pub fn call_method( &mut self, method: &str, args: Vec<Value>, ) -> Result<Value, String>
Call a method on this value with given arguments
Sourcepub fn get_property(&self, property: &str) -> Option<Value>
pub fn get_property(&self, property: &str) -> Option<Value>
Get a property from this object
Examples found in repository?
examples/debug_conditions.rs (line 51)
9fn test_simple_conditions() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Testing Simple Conditions ===");
11
12 // Create Knowledge Base
13 let kb = KnowledgeBase::new("TestConditions");
14
15 // Test compound condition with &&
16 let compound_rule = r#"rule "CompoundRule" { when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed then TestCar.result = "compound_fired"; }"#;
17
18 println!("Testing rule: {}", compound_rule);
19
20 // Parse and add rule
21 let rules = GRLParser::parse_rules(compound_rule)?;
22 let rule = rules.into_iter().next().unwrap();
23 println!("Parsed rule: {:?}", rule);
24
25 let _ = kb.add_rule(rule);
26
27 // Create engine with debug mode
28 let config = EngineConfig {
29 max_cycles: 10,
30 timeout: None,
31 enable_stats: true,
32 debug_mode: true,
33 };
34 let engine = RustRuleEngine::with_config(kb, config);
35
36 // Create facts
37 let facts = Facts::new();
38
39 // Create simple TestCar object with all needed properties
40 let test_car = FactHelper::create_object(vec![
41 ("speedUp", Value::Boolean(true)),
42 ("speed", Value::Number(30.0)),
43 ("maxSpeed", Value::Number(100.0)),
44 ("result", Value::String("not_fired".to_string())),
45 ]);
46
47 facts.add_value("TestCar", test_car)?;
48
49 println!("\n🏁 Before execution:");
50 if let Some(car) = facts.get("TestCar") {
51 println!(" TestCar.speedUp = {:?}", car.get_property("speedUp"));
52 println!(" TestCar.speed = {:?}", car.get_property("speed"));
53 println!(" TestCar.maxSpeed = {:?}", car.get_property("maxSpeed"));
54 println!(" TestCar.result = {:?}", car.get_property("result"));
55 }
56
57 // Execute rules
58 println!("\n🚀 Executing rule...");
59 let result = engine.execute(&facts)?;
60
61 println!("Rules fired: {}", result.rules_fired);
62
63 println!("\n🏁 After execution:");
64 if let Some(car) = facts.get("TestCar") {
65 println!(" TestCar.speedUp = {:?}", car.get_property("speedUp"));
66 println!(" TestCar.result = {:?}", car.get_property("result"));
67 }
68
69 Ok(())
70}More examples
examples/advanced_method_calls.rs (line 55)
9fn demo_method_calls() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Advanced Method Calls ===");
11
12 // Create Knowledge Base
13 let kb = KnowledgeBase::new("MethodCallsDemo");
14
15 // Define rule with simpler condition first
16 let speedup_rule = r#"rule "SpeedUp" salience 10 {
17 when TestCar.speedUp == true
18 then TestCar.Speed = 70;
19 }"#;
20
21 // Parse and add rule
22 let rules = GRLParser::parse_rules(speedup_rule)?;
23 let rule = rules.into_iter().next().unwrap();
24 let _ = kb.add_rule(rule);
25
26 // Create engine with debug mode
27 let config = EngineConfig {
28 max_cycles: 10,
29 timeout: None,
30 enable_stats: true,
31 debug_mode: true,
32 };
33 let engine = RustRuleEngine::with_config(kb, config);
34
35 // Create facts
36 let facts = Facts::new();
37
38 // Create TestCar object using helper
39 let test_car = FactHelper::create_test_car(
40 true, // speedUp
41 50.0, // speed
42 100.0, // maxSpeed
43 10.0, // speedIncrement
44 );
45
46 // Create DistanceRecord object using helper
47 let distance_record = FactHelper::create_distance_record(0.0);
48
49 // Add facts
50 facts.add_value("TestCar", test_car)?;
51 facts.add_value("DistanceRecord", distance_record)?;
52
53 println!("\n🏁 Initial state:");
54 if let Some(car) = facts.get("TestCar") {
55 if let Some(speed) = car.get_property("Speed") {
56 println!(" TestCar.Speed = {:?}", speed);
57 }
58 if let Some(speed_up) = car.get_property("speedUp") {
59 println!(" TestCar.speedUp = {:?}", speed_up);
60 }
61 }
62
63 // Execute rules multiple cycles to see progression
64 println!("\n🚀 Executing SpeedUp rule multiple times...");
65 for i in 1..=3 {
66 println!("\n--- Cycle {} ---", i);
67 let result = engine.execute(&facts)?;
68
69 println!("Rules fired: {}", result.rules_fired);
70
71 if let Some(car) = facts.get("TestCar") {
72 if let Some(speed) = car.get_property("Speed") {
73 println!("TestCar.Speed after cycle {}: {:?}", i, speed);
74 }
75 }
76
77 // Check if we reached max speed
78 if let Some(car) = facts.get("TestCar") {
79 if let Some(speed) = car.get_property("speed") {
80 if let Some(max_speed) = car.get_property("maxSpeed") {
81 if speed.to_number() >= max_speed.to_number() {
82 println!("🏁 Max speed reached!");
83 break;
84 }
85 }
86 }
87 }
88 }
89
90 println!("\n📊 Final Results:");
91 if let Some(car) = facts.get("TestCar") {
92 if let Some(speed) = car.get_property("Speed") {
93 println!(" Final TestCar.Speed = {:?}", speed);
94 }
95 }
96
97 Ok(())
98}examples/complete_speedup_demo.rs (line 68)
9fn demo_complete_speedup_rule() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Complete SpeedUp Rule with Method Calls ===");
11 println!("Implementing the exact rule from the requirement:");
12 println!("rule \"SpeedUp\" salience 10");
13 println!("when");
14 println!(" $TestCar : TestCarClass( speedUp == true && speed < maxSpeed )");
15 println!(" $DistanceRecord : DistanceRecordClass()");
16 println!("then");
17 println!(" $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement);");
18 println!(" update($TestCar);");
19 println!(" $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed);");
20 println!(" update($DistanceRecord);");
21 println!("end\n");
22
23 // Create Knowledge Base
24 let kb = KnowledgeBase::new("SpeedUpDemo");
25
26 // For now, we'll use a simplified version that works with our current parser
27 let speedup_rule = r#"rule "SpeedUp" salience 10 {
28 when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed
29 then $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement); update($TestCar); $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed); update($DistanceRecord);
30 }"#;
31
32 // Parse and add rule
33 let rules = GRLParser::parse_rules(speedup_rule)?;
34 let rule = rules.into_iter().next().unwrap();
35 let _ = kb.add_rule(rule);
36
37 // Create engine with debug mode
38 let config = EngineConfig {
39 max_cycles: 10,
40 timeout: None,
41 enable_stats: true,
42 debug_mode: true,
43 };
44 let engine = RustRuleEngine::with_config(kb, config);
45
46 // Create facts
47 let facts = Facts::new();
48
49 // Create TestCar object - initial speed less than max
50 let test_car = FactHelper::create_test_car(
51 true, // speedUp
52 30.0, // speed (less than maxSpeed)
53 100.0, // maxSpeed
54 15.0, // speedIncrement
55 );
56
57 // Create DistanceRecord object
58 let distance_record = FactHelper::create_distance_record(0.0);
59
60 // Add facts
61 facts.add_value("TestCar", test_car)?;
62 facts.add_value("DistanceRecord", distance_record)?;
63
64 println!("🏁 Initial state:");
65 if let Some(car) = facts.get("TestCar") {
66 println!(
67 " TestCar.speed = {:?}",
68 car.get_property("speed").unwrap_or(Value::Null)
69 );
70 println!(
71 " TestCar.Speed = {:?}",
72 car.get_property("Speed").unwrap_or(Value::Null)
73 );
74 println!(
75 " TestCar.maxSpeed = {:?}",
76 car.get_property("maxSpeed").unwrap_or(Value::Null)
77 );
78 println!(
79 " TestCar.speedUp = {:?}",
80 car.get_property("speedUp").unwrap_or(Value::Null)
81 );
82 println!(
83 " TestCar.SpeedIncrement = {:?}",
84 car.get_property("SpeedIncrement").unwrap_or(Value::Null)
85 );
86 }
87 if let Some(record) = facts.get("DistanceRecord") {
88 println!(
89 " DistanceRecord.TotalDistance = {:?}",
90 record.get_property("TotalDistance").unwrap_or(Value::Null)
91 );
92 }
93
94 // Execute rules multiple cycles
95 println!("\n🚀 Executing SpeedUp rule...");
96 for i in 1..=5 {
97 println!("\n--- Cycle {} ---", i);
98 let result = engine.execute(&facts)?;
99
100 println!("Rules fired: {}", result.rules_fired);
101
102 if let Some(car) = facts.get("TestCar") {
103 println!(
104 "TestCar.Speed = {:?}",
105 car.get_property("Speed").unwrap_or(Value::Null)
106 );
107 println!(
108 "TestCar.speed = {:?}",
109 car.get_property("speed").unwrap_or(Value::Null)
110 );
111 }
112 if let Some(record) = facts.get("DistanceRecord") {
113 println!(
114 "DistanceRecord.TotalDistance = {:?}",
115 record.get_property("TotalDistance").unwrap_or(Value::Null)
116 );
117 }
118
119 // Check if we reached max speed
120 if let Some(car) = facts.get("TestCar") {
121 if let Some(speed) = car.get_property("speed") {
122 if let Some(max_speed) = car.get_property("maxSpeed") {
123 if speed.to_number() >= max_speed.to_number() {
124 println!("🏁 Max speed reached! Rule will no longer fire.");
125 break;
126 }
127 }
128 }
129 }
130
131 if result.rules_fired == 0 {
132 println!("ℹ️ No rules fired this cycle.");
133 break;
134 }
135 }
136
137 println!("\n📊 Final Summary:");
138 println!("✅ Successfully demonstrated method calls in GRL:");
139 println!(" • Method calls: $Object.method(args)");
140 println!(" • Property access: $Object.Property");
141 println!(" • Arithmetic expressions: $A.prop + $B.prop");
142 println!(" • update() function calls");
143 println!(" • Complex conditions with && operator");
144
145 Ok(())
146}Trait Implementations§
Source§impl<'de> Deserialize<'de> for Value
impl<'de> Deserialize<'de> for Value
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
impl StructuralPartialEq for Value
Auto Trait Implementations§
impl Freeze for Value
impl RefUnwindSafe for Value
impl Send for Value
impl Sync for Value
impl Unpin for Value
impl UnwindSafe for Value
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more