use recoco::builder::FlowBuilder;
use recoco::execution::evaluator::evaluate_transient_flow;
use recoco::ops::sdk::*;
use recoco::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::sync::Arc;
pub struct ReverseStringExecutor;
#[async_trait]
impl SimpleFunctionExecutor for ReverseStringExecutor {
async fn evaluate(&self, input: Vec<value::Value>) -> Result<value::Value> {
let val = &input[0];
let s = val.as_str()?;
let reversed: String = s.chars().rev().collect();
Ok(value::Value::Basic(value::BasicValue::Str(reversed.into())))
}
}
pub struct ReverseStringFactory;
#[derive(Deserialize, Serialize)]
pub struct EmptySpec {}
#[async_trait]
impl SimpleFunctionFactoryBase for ReverseStringFactory {
type Spec = EmptySpec;
type ResolvedArgs = ();
fn name(&self) -> &str {
"ReverseString"
}
async fn analyze<'a>(
&'a self,
_spec: &'a Self::Spec,
args_resolver: &mut OpArgsResolver<'a>,
_context: &FlowInstanceContext,
) -> Result<SimpleFunctionAnalysisOutput<Self::ResolvedArgs>> {
args_resolver
.next_arg("text")?
.expect_type(&ValueType::Basic(BasicValueType::Str))?
.required()?;
let output_schema = schema::make_output_type(schema::BasicValueType::Str);
Ok(SimpleFunctionAnalysisOutput {
resolved_args: (),
output_schema,
behavior_version: None,
})
}
async fn build_executor(
self: Arc<Self>,
_spec: Self::Spec,
_resolved_args: Self::ResolvedArgs,
_context: Arc<FlowInstanceContext>,
) -> Result<impl SimpleFunctionExecutor> {
Ok(ReverseStringExecutor)
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
recoco::lib_context::init_lib_context(Some(recoco::settings::Settings::default())).await?;
println!("Registering custom operation 'ReverseString'...");
recoco::ops::register_factory(
"ReverseString".to_string(),
ExecutorFactory::SimpleFunction(Arc::new(ReverseStringFactory)),
)?;
let mut builder = FlowBuilder::new("custom_op_flow").await?;
let text_input = builder.add_direct_input(
"text".to_string(),
schema::make_output_type(schema::BasicValueType::Str),
)?;
let reversed = builder
.transform(
"ReverseString".to_string(),
json!({}).as_object().unwrap().clone(),
vec![(text_input, Some("text".to_string()))],
None,
"reverser".to_string(),
)
.await?;
builder.set_direct_output(reversed)?;
let flow = builder.build_transient_flow().await?;
let input_text = "Recoco is Awesome";
println!("Input: {}", input_text);
let input_val = value::Value::Basic(value::BasicValue::Str(input_text.into()));
let result = evaluate_transient_flow(&flow.0, &vec![input_val]).await?;
println!("Output: {:?}", result);
if let value::Value::Basic(value::BasicValue::Str(s)) = result {
assert_eq!(s.as_ref(), "emosewA si ocoCeR");
println!("Verification successful!");
}
Ok(())
}