use ops_rs::prelude::*;
use ops_rs::{dry_get, dry_put, dry_require, wet_put_ref, wet_require_ref};
use std::sync::Arc;
struct GreetingService {
prefix: String,
}
impl GreetingService {
fn new(prefix: &str) -> Self {
Self {
prefix: prefix.to_string(),
}
}
fn greet(&self, name: &str) -> String {
format!("{} {}!", self.prefix, name)
}
}
struct HelloOp;
#[async_trait]
impl Op<String> for HelloOp {
async fn perform(&self, dry: &mut DryContext, wet: &mut WetContext) -> OpResult<String> {
let name: String = dry_require!(dry, name)?;
let greeting_service: Arc<GreetingService> = wet_require_ref!(wet, greeting_service)?;
Ok(greeting_service.greet(&name))
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("HelloOp")
.description("Greets a person using a greeting service")
.build()
}
}
struct MathOp;
#[async_trait]
impl Op<i32> for MathOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<i32> {
let x: i32 = dry_require!(dry, x)?;
Ok(x * 2 + 1)
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("MathOp")
.description("Performs math operation: x * 2 + 1")
.build()
}
}
struct ComplexOp;
#[async_trait]
impl Op<String> for ComplexOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<String> {
let data: Vec<String> = dry_require!(dry, data)?;
if data.is_empty() {
Err(OpError::ExecutionFailed("Empty input".to_string()))
} else {
Ok(data.join(", "))
}
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("ComplexOp")
.description("Joins a vector of strings")
.build()
}
}
struct AddOp;
#[async_trait]
impl Op<i32> for AddOp {
async fn perform(&self, dry: &mut DryContext, _wet: &mut WetContext) -> OpResult<i32> {
let a: i32 = dry_require!(dry, a)?;
let b: i32 = dry_require!(dry, b)?;
Ok(a + b)
}
fn metadata(&self) -> OpMetadata {
OpMetadata::builder("AddOp")
.description("Adds two integers")
.build()
}
}
#[tokio::main]
async fn main() -> OpResult<()> {
tracing_subscriber::fmt::init();
println!("=== Testing modern Op implementations with dry/wet contexts ===");
let mut wet = WetContext::new();
let greeting_service = GreetingService::new("Hello");
wet_put_ref!(wet, greeting_service);
let mut dry = DryContext::new();
let name = "World".to_string();
dry_put!(dry, name);
let hello_op = HelloOp;
let result = hello_op.perform(&mut dry, &mut wet).await?;
println!("HelloOp result: {}", result);
let mut dry = DryContext::new();
let x = 5;
dry_put!(dry, x);
let math_op = MathOp;
let result = math_op.perform(&mut dry, &mut wet).await?;
println!("MathOp result: {}", result);
let mut dry = DryContext::new();
let data = vec!["a".to_string(), "b".to_string(), "c".to_string()];
dry_put!(dry, data);
let complex_op = ComplexOp;
let result = complex_op.perform(&mut dry, &mut wet).await?;
println!("ComplexOp result: {}", result);
let mut dry = DryContext::new();
let data: Vec<String> = vec![];
dry_put!(dry, data);
match complex_op.perform(&mut dry, &mut wet).await {
Ok(_) => println!("Unexpected success"),
Err(e) => println!("Expected error: {}", e),
}
let mut dry = DryContext::new();
let a = 10;
let b = 20;
dry_put!(dry, a);
dry_put!(dry, b);
let add_op = AddOp;
let result = add_op.perform(&mut dry, &mut wet).await?;
println!("AddOp result: {}", result);
let mut empty_dry = DryContext::new();
match hello_op.perform(&mut empty_dry, &mut wet).await {
Ok(_) => println!("Unexpected success"),
Err(e) => println!("Expected missing input error: {}", e),
}
let optional_value: Option<String> = dry_get!(empty_dry, name);
println!("Optional value from empty context: {:?}", optional_value);
println!("\n=== Op Metadata ===");
println!("HelloOp: {}", hello_op.metadata().name);
println!("MathOp: {}", math_op.metadata().name);
println!("ComplexOp: {}", complex_op.metadata().name);
println!("AddOp: {}", add_op.metadata().name);
Ok(())
}