use ops_rs::prelude::*;
use ops_rs::{abort, break_loop, continue_loop, repeat_until};
#[derive(Debug)]
struct ControlFlowOp {
id: i32,
action: ControlAction,
}
#[derive(Debug)]
enum ControlAction {
Continue, Skip, Break, Abort, }
impl ControlFlowOp {
fn new(id: i32, action: ControlAction) -> Self {
Self { id, action }
}
}
#[async_trait]
impl Op<String> for ControlFlowOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<String> {
let iteration = dry.get::<usize>("iteration").unwrap_or(0);
println!("Op {} executing in iteration {}", self.id, iteration);
match self.action {
ControlAction::Continue => {
println!(" → Processing normally");
Ok(format!("Op{}-Iter{}", self.id, iteration))
}
ControlAction::Skip => {
println!(" → Skipping rest of this iteration (continue_loop!)");
continue_loop!(dry);
}
ControlAction::Break => {
println!(" → Breaking out of entire loop (break_loop!)");
break_loop!(dry);
}
ControlAction::Abort => {
println!(" → Aborting entire operation (abort!)");
abort!(dry, "Operation aborted by ControlFlowOp");
}
}
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder(&format!("ControlFlowOp-{}", self.id)).build()
}
}
#[derive(Debug)]
struct ConditionCheckOp {
max_iterations: usize,
}
impl ConditionCheckOp {
fn new(max_iterations: usize) -> Self {
Self { max_iterations }
}
}
#[async_trait]
impl Op<String> for ConditionCheckOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<String> {
let iteration = dry.get::<usize>("iteration").unwrap_or(0);
let should_continue = iteration < self.max_iterations;
println!(
"ConditionCheck: iteration {} < {}: {}",
iteration, self.max_iterations, should_continue
);
dry.insert("should_continue", should_continue);
Ok(format!(
"ConditionCheck-Iter{}-Continue{}",
iteration, should_continue
))
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("ConditionCheckOp").build()
}
}
repeat_until! {
NormalLoopWithContinue<String> = {
counter: "iteration",
condition: "should_continue",
max_iterations: 5,
ops: [
ControlFlowOp::new(1, ControlAction::Continue),
ControlFlowOp::new(2, ControlAction::Skip), ControlFlowOp::new(3, ControlAction::Continue), ConditionCheckOp::new(3)
]
}
}
repeat_until! {
LoopWithBreak<String> = {
counter: "iteration",
condition: "should_continue",
max_iterations: 10,
ops: [
ControlFlowOp::new(1, ControlAction::Continue),
ControlFlowOp::new(2, ControlAction::Break), ControlFlowOp::new(3, ControlAction::Continue), ConditionCheckOp::new(10)
]
}
}
repeat_until! {
LoopWithAbort<String> = {
counter: "iteration",
condition: "should_continue",
max_iterations: 10,
ops: [
ControlFlowOp::new(1, ControlAction::Continue),
ControlFlowOp::new(2, ControlAction::Abort), ControlFlowOp::new(3, ControlAction::Continue), ConditionCheckOp::new(10)
]
}
}
repeat_until! {
ComplexControlFlow<String> -> last = {
counter: "iteration",
condition: "should_continue",
max_iterations: 20,
ops: [
ControlFlowOp::new(1, ControlAction::Continue),
ConditionCheckOp::new(5) ]
}
}
#[tokio::main]
async fn main() -> OpResult<()> {
let mut dry = DryContext::new();
let mut wet = WetContext::new();
println!(" LOOP CONTROL FLOW DEMONSTRATIONS \n");
println!("=== Example 1: continue_loop! behavior ===");
dry.insert("should_continue", true);
let normal_loop = NormalLoopWithContinue::new();
match normal_loop.perform(&mut dry, &mut wet).await {
Ok(results) => {
println!("OK Normal loop completed with {} results:", results.len());
for (i, result) in results.iter().enumerate() {
println!(" Result {}: {}", i, result);
}
}
Err(e) => println!("ERR Error: {}", e),
}
println!("\n=== Example 2: break_loop! behavior ===");
dry.clear_control_flags();
dry.insert("should_continue", true);
let break_loop = LoopWithBreak::new();
match break_loop.perform(&mut dry, &mut wet).await {
Ok(results) => {
println!(
"OK Loop with break completed with {} results:",
results.len()
);
for (i, result) in results.iter().enumerate() {
println!(" Result {}: {}", i, result);
}
}
Err(e) => println!("ERR Error: {}", e),
}
println!("\n=== Example 3: abort! behavior ===");
dry.clear_control_flags();
dry.insert("should_continue", true);
let abort_loop = LoopWithAbort::new();
match abort_loop.perform(&mut dry, &mut wet).await {
Ok(results) => {
println!(
"OK Loop with abort completed with {} results:",
results.len()
);
for (i, result) in results.iter().enumerate() {
println!(" Result {}: {}", i, result);
}
}
Err(e) => println!("ERR Expected abort error: {}", e),
}
println!("\n=== Example 4: Condition-based loop ===");
dry.clear_control_flags();
dry.insert("should_continue", true);
let complex_loop = ComplexControlFlow::new();
match complex_loop.perform(&mut dry, &mut wet).await {
Ok(result) => {
println!("OK Complex loop completed with result: {}", result);
}
Err(e) => println!("ERR Error: {}", e),
}
println!("\n SUMMARY:");
println!("• continue_loop!: Skips rest of current iteration, moves to next");
println!("• break_loop!: Exits the entire loop immediately");
println!("• abort!: Stops everything and returns an error");
println!("• condition variable: Controls whether loop continues");
Ok(())
}