Skip to main content

custom_operators/
custom_operators.rs

1//! Custom operator registration and usage.
2//!
3//! Run with: cargo run --example custom_operators
4
5use fsm_guards::{evaluate, EvalCtx};
6use serde_json::{json, Value};
7use std::sync::Arc;
8
9fn main() {
10    // ── state_in: membership check ─────────────────────────────────────────
11    let ctx = EvalCtx::new().with_op("state_in", |args| {
12        Ok(Value::Bool(args[1..].contains(&args[0])))
13    });
14
15    let rule = json!({"state_in": [{"var": "status"}, "active", "pending"]});
16    println!("active → {}", evaluate(&rule, &json!({"status": "active"}), &ctx).unwrap()); // true
17    println!("blocked → {}", evaluate(&rule, &json!({"status": "blocked"}), &ctx).unwrap()); // false
18
19    // ── multiple operators ─────────────────────────────────────────────────
20    let ctx = EvalCtx::new()
21        .with_op("state_in", |args| Ok(Value::Bool(args[1..].contains(&args[0]))))
22        .with_op("days_since", |args| {
23            // Stub: in production this would compute real elapsed days
24            let recorded = args[0].as_f64().unwrap_or(0.0);
25            let now = args[1].as_f64().unwrap_or(0.0);
26            Ok(json!(now - recorded))
27        });
28
29    let rule = json!({"and": [
30        {"state_in": [{"var": "status"}, "active", "pending"]},
31        {"<": [{"days_since": [{"var": "created_at"}, 1722470400.0]}, 30]}
32    ]});
33    let data = json!({"status": "active", "created_at": 1720000000.0});
34    println!("compound: {}", evaluate(&rule, &data, &ctx).unwrap());
35
36    // ── Arc sharing across threads ─────────────────────────────────────────
37    let shared_ctx = Arc::new(
38        EvalCtx::new().with_op("always_true", |_| Ok(Value::Bool(true))),
39    );
40
41    let handles: Vec<_> = (0..4)
42        .map(|i| {
43            let ctx = Arc::clone(&shared_ctx);
44            let rule = json!({"always_true": []});
45            std::thread::spawn(move || {
46                let result = evaluate(&rule, &json!({}), &ctx).unwrap();
47                println!("thread {i}: {result}");
48            })
49        })
50        .collect();
51
52    for h in handles {
53        h.join().unwrap();
54    }
55}