use async_trait::async_trait;
use std::fmt;
use std::marker::PhantomData;
use crate::error::AnchorChainError;
use crate::{link::Link, node::Node};
#[derive(Debug)]
pub struct Chain<I, O, L> {
link: L,
_input: PhantomData<I>,
_output: PhantomData<O>,
}
impl<I, O, L> Chain<I, O, L>
where
L: Node<Input = I, Output = O> + Send + Sync + std::fmt::Debug,
I: std::fmt::Debug,
O: std::fmt::Debug,
{
pub fn new(link: L) -> Self {
Chain {
link,
_input: PhantomData,
_output: PhantomData,
}
}
pub async fn process(&self, input: I) -> Result<O, AnchorChainError> {
self.link.process(input).await
}
}
#[async_trait]
impl<I, O, L> Node for Chain<I, O, L>
where
L: Node<Input = I, Output = O> + Send + Sync + fmt::Debug,
I: fmt::Debug + Send + Sync,
O: fmt::Debug + Send + Sync,
{
type Input = I;
type Output = O;
async fn process(&self, input: Self::Input) -> Result<Self::Output, AnchorChainError> {
self.process(input).await
}
}
pub struct ChainBuilder {}
impl ChainBuilder {
pub fn new() -> Self {
ChainBuilder {}
}
pub fn link<I, N>(self, node: N) -> LinkedChainBuilder<I, N>
where
N: Node<Input = I> + Send + Sync + std::fmt::Debug,
I: Send,
{
LinkedChainBuilder {
link: node,
_input: PhantomData,
}
}
}
impl Default for ChainBuilder {
fn default() -> Self {
ChainBuilder::new()
}
}
pub struct LinkedChainBuilder<I, L> {
link: L,
_input: PhantomData<I>,
}
impl<I, L> LinkedChainBuilder<I, L>
where
L: Node<Input = I> + Send + Sync + std::fmt::Debug,
I: Send,
{
pub fn link<N>(self, next: N) -> LinkedChainBuilder<I, Link<L, N>>
where
N: Node<Input = L::Output> + Send + Sync + std::fmt::Debug,
L::Output: Send,
Link<L, N>: Node<Input = I>,
{
LinkedChainBuilder {
link: Link {
node: self.link,
next,
},
_input: PhantomData,
}
}
pub fn build(self) -> Chain<I, L::Output, L>
where
L: Node,
{
Chain {
link: self.link,
_input: PhantomData,
_output: PhantomData,
}
}
}