use async_trait::async_trait;
use std::fmt;
use std::sync::Arc;
use super::{SkillInput};
use crate::skills::error::{Result, SkillError, SkillOutput};
#[async_trait]
pub trait Skill: fmt::Debug + Send + Sync {
fn name(&self) -> String;
fn description(&self) -> String;
async fn execute(&self, input: SkillInput) -> Result<SkillOutput>;
fn validate(&self) -> Result<()>;
fn version(&self) -> String {
"1.0.0".to_string()
}
fn author(&self) -> Option<String> {
None
}
fn tags(&self) -> Vec<String> {
Vec::new()
}
fn dependencies(&self) -> Vec<String> {
Vec::new()
}
fn supports(&self, _capability: &str) -> bool {
false
}
async fn before_execute(&self, _input: &SkillInput) -> Result<()> {
Ok(())
}
async fn after_execute(&self, _input: &SkillInput, _output: &SkillOutput) -> Result<()> {
Ok(())
}
async fn on_error(&self, _input: &SkillInput, error: &SkillError) -> SkillError {
error.clone()
}
}
pub struct SkillBox {
pub inner: Arc<dyn Skill>,
}
impl SkillBox {
pub fn new<S: Skill + 'static>(skill: S) -> Self {
SkillBox {
inner: Arc::new(skill),
}
}
}
#[async_trait]
impl Skill for SkillBox {
fn name(&self) -> String {
self.inner.name()
}
fn description(&self) -> String {
self.inner.description()
}
async fn execute(&self, input: SkillInput) -> Result<SkillOutput> {
self.inner.execute(input).await
}
fn validate(&self) -> Result<()> {
self.inner.validate()
}
fn version(&self) -> String {
self.inner.version()
}
fn author(&self) -> Option<String> {
self.inner.author()
}
fn tags(&self) -> Vec<String> {
self.inner.tags()
}
fn supports(&self, capability: &str) -> bool {
self.inner.supports(capability)
}
fn dependencies(&self) -> Vec<String> {
self.inner.dependencies()
}
async fn before_execute(&self, input: &SkillInput) -> Result<()> {
self.inner.before_execute(input).await
}
async fn after_execute(&self, input: &SkillInput, output: &SkillOutput) -> Result<()> {
self.inner.after_execute(input, output).await
}
async fn on_error(&self, input: &SkillInput, error: &SkillError) -> SkillError {
self.inner.on_error(input, error).await
}
}
impl fmt::Debug for SkillBox {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SkillBox")
.field("name", &self.inner.name())
.field("version", &self.inner.version())
.finish()
}
}
impl Clone for SkillBox {
fn clone(&self) -> Self {
SkillBox {
inner: Arc::clone(&self.inner),
}
}
}