Skip to main content

guard/
guard.rs

1//! Conditional execution with `guard` blocks.
2//!
3//! A guard runs its body only when a boolean `GuardSource` resolves to true.
4//! The guard reference is checked at compile time, so an unresolved source
5//! fails `compile()` rather than the run. Outputs produced inside the body
6//! are visible to later steps in the parent pipeline.
7
8use panopticon_core::{params, prelude::*};
9use std::time::Duration;
10
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    // ── Basic guard: Compare produces true, body executes ──
13    println!("=== Guard (true) ===");
14    {
15        let mut pipe = Pipeline::default();
16        pipe.var("status_code", 200i64)?;
17
18        pipe.step::<Compare>(
19            "is_ok",
20            params!(
21                "left" => Param::reference("status_code"),
22                "op" => "eq",
23                "right" => 200i64,
24                "name" => "should_run",
25            ),
26        )?;
27
28        pipe.guard("check", GuardSource::boolean("is_ok.should_run"), |body| {
29            body.step::<SetVar>(
30                "produce",
31                params!("name" => "result", "value" => "guard body executed"),
32            )?;
33            Ok(())
34        })?;
35
36        pipe.hook(Logger::new().writer(std::io::stdout()));
37        pipe.hook(Timeout::new(Duration::from_secs(5)));
38
39        let complete = pipe.compile()?.run().wait()?;
40        complete.debug();
41    }
42
43    // ── Guard skipped: Compare produces false ──
44    println!("\n=== Guard (false) ===");
45    {
46        let mut pipe = Pipeline::default();
47        pipe.var("status_code", 404i64)?;
48
49        pipe.step::<Compare>(
50            "is_ok",
51            params!(
52                "left" => Param::reference("status_code"),
53                "op" => "eq",
54                "right" => 200i64,
55                "name" => "should_run",
56            ),
57        )?;
58
59        pipe.guard("check", GuardSource::boolean("is_ok.should_run"), |body| {
60            body.step::<SetVar>(
61                "produce",
62                params!("name" => "result", "value" => "should not appear"),
63            )?;
64            Ok(())
65        })?;
66
67        pipe.hook(Logger::new().writer(std::io::stdout()));
68
69        let complete = pipe.compile()?.run().wait()?;
70        complete.debug();
71    }
72
73    // ── Guard output used by downstream step ──
74    println!("\n=== Guard output used downstream ===");
75    {
76        let mut pipe = Pipeline::default();
77        pipe.var("count", 5i64)?;
78
79        pipe.step::<Compare>(
80            "has_results",
81            params!(
82                "left" => Param::reference("count"),
83                "op" => "gt",
84                "right" => 0i64,
85                "name" => "flag",
86            ),
87        )?;
88
89        pipe.guard("gate", GuardSource::boolean("has_results.flag"), |body| {
90            body.step::<SetVar>(
91                "create",
92                params!("name" => "message", "value" => "from inside guard"),
93            )?;
94            Ok(())
95        })?;
96
97        pipe.step::<SetVar>(
98            "consume",
99            params!(
100                "name" => "final_output",
101                "value" => Param::template(vec![
102                    Param::literal("received: "),
103                    Param::reference("message"),
104                ]),
105            ),
106        )?;
107
108        pipe.hook(Logger::new().writer(std::io::stdout()));
109
110        let complete = pipe.compile()?.run().wait()?;
111        complete.debug();
112    }
113
114    // ── Error: unresolved guard reference ──
115    println!("\n=== Guard unresolved reference ===");
116    {
117        let mut pipe = Pipeline::default();
118
119        pipe.guard("check", GuardSource::boolean("nonexistent"), |_body| Ok(()))?;
120
121        match pipe.compile() {
122            Err(e) => println!("  Caught: {}", e),
123            Ok(_) => println!("  ERROR: should have failed!"),
124        }
125    }
126
127    Ok(())
128}