use std::{any::Any, sync::Arc};
use async_trait::async_trait;
use dyn_clone::DynClone;
use super::{
errors::TaskError,
executor::EvaluatedTransition,
node::NodeId,
task::Task,
transition::{MarkedTransition, Transition},
};
pub trait NodeArg: Send + Sync + DynClone + 'static {}
impl<T: Send + Sync + std::fmt::Debug + 'static + Clone> NodeArg for T {}
#[async_trait]
pub trait TaskNode: Send + Sync + DynClone + Any {
type Input: NodeArg;
type Output: NodeArg;
type Error: std::error::Error + Send + Sync + 'static;
async fn evaluate(
&self,
node_id: &DynNodeId<Self>,
input: &Self::Input,
) -> Result<Self::Output, Self::Error>;
}
pub type DynNodeId<T> = NodeId<
dyn TaskNode<
Input = <T as TaskNode>::Input,
Output = <T as TaskNode>::Output,
Error = <T as TaskNode>::Error,
>,
>;
dyn_clone::clone_trait_object!(
TaskNode<
Input = dyn NodeArg,
Output = dyn NodeArg,
Error = dyn std::error::Error + Send + Sync,
>
);
#[async_trait]
impl<Input: NodeArg, Output: NodeArg, Error: std::error::Error + Send + Sync + 'static> TaskNode
for Box<dyn TaskNode<Input = Input, Output = Output, Error = Error>>
{
type Input = Input;
type Output = Output;
type Error = Error;
async fn evaluate(
&self,
node_id: &NodeId<
dyn TaskNode<Input = Self::Input, Output = Self::Output, Error = Self::Error>,
>,
input: &Self::Input,
) -> Result<Self::Output, Self::Error> {
self.as_ref().evaluate(node_id, input).await
}
}
dyn_clone::clone_trait_object!(<Input, Output, Error> TaskNode<Input = Input, Output = Output, Error = Error>);
#[doc(hidden)]
pub trait RegisterTransition<From: TaskNode + ?Sized>: 'static {
#[doc(hidden)]
fn register<Input: NodeArg + Clone, Output: NodeArg + Clone>(
self,
task: &mut Task<Input, Output>,
from: NodeId<From>,
) -> Result<(), TaskError>;
}
#[doc(hidden)]
pub trait RegisterTransitionAsync<From: TaskNode + ?Sized>: 'static {
#[doc(hidden)]
fn register_async<Input: NodeArg + Clone, Output: NodeArg + Clone>(
self,
task: &mut Task<Input, Output>,
from: NodeId<From>,
) -> Result<(), TaskError>;
}
pub(super) trait TransitionResult<From: TaskNode + ?Sized> {
fn into_transition(self) -> Transition;
}
impl<From, To> TransitionResult<From> for MarkedTransition<To>
where
From: TaskNode + 'static + ?Sized,
To: TaskNode + ?Sized,
{
fn into_transition(self) -> Transition {
self.into_inner()
}
}
impl<From> TransitionResult<From> for Transition
where
From: TaskNode + 'static + ?Sized,
{
fn into_transition(self) -> Transition {
self
}
}
#[async_trait]
pub(crate) trait AnyNodeExecutor: Any + Send + Sync + std::fmt::Debug + DynClone {
fn node_as_any(&self) -> &dyn Any;
fn transition_is_set(&self) -> bool;
async fn evaluate_next(
&self,
context: Arc<dyn Any + Send + Sync>,
) -> Result<EvaluatedTransition, TaskError>;
}
dyn_clone::clone_trait_object!(AnyNodeExecutor);