use async_trait::async_trait;
use std::sync::Arc;
#[async_trait]
pub trait Callable: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> Option<&str> {
None
}
async fn run(&self, input: &str) -> anyhow::Result<String>;
}
pub type DynCallable = Arc<dyn Callable>;
#[allow(dead_code)]
pub struct FnCallable<F>
where
F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
{
name: String,
description: Option<String>,
func: F,
}
#[allow(dead_code)]
impl<F> FnCallable<F>
where
F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
{
pub fn new(name: impl Into<String>, func: F) -> Self {
Self {
name: name.into(),
description: None,
func,
}
}
pub fn with_description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
}
#[async_trait]
impl<F> Callable for FnCallable<F>
where
F: Fn(&str) -> anyhow::Result<String> + Send + Sync,
{
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
self.description.as_deref()
}
async fn run(&self, input: &str) -> anyhow::Result<String> {
(self.func)(input)
}
}
#[allow(dead_code)]
pub struct AsyncFnCallable<F, Fut>
where
F: Fn(String) -> Fut + Send + Sync,
Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
{
name: String,
description: Option<String>,
func: F,
_phantom: std::marker::PhantomData<fn() -> Fut>,
}
#[allow(dead_code)]
impl<F, Fut> AsyncFnCallable<F, Fut>
where
F: Fn(String) -> Fut + Send + Sync,
Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
{
pub fn new(name: impl Into<String>, func: F) -> Self {
Self {
name: name.into(),
description: None,
func,
_phantom: std::marker::PhantomData,
}
}
pub fn with_description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
}
#[async_trait]
impl<F, Fut> Callable for AsyncFnCallable<F, Fut>
where
F: Fn(String) -> Fut + Send + Sync,
Fut: std::future::Future<Output = anyhow::Result<String>> + Send + Sync,
{
fn name(&self) -> &str {
&self.name
}
fn description(&self) -> Option<&str> {
self.description.as_deref()
}
async fn run(&self, input: &str) -> anyhow::Result<String> {
(self.func)(input.to_string()).await
}
}