use std::marker::PhantomData;
pub trait OkFlow<InputOk> {
type OutputOk;
fn apply_ok(&self, input: InputOk) -> Self::OutputOk;
fn then_ok<Next>(self, next: Next) -> OkFlowChain<Self, Next, InputOk>
where
Self: Sized,
Next: OkFlow<Self::OutputOk>,
{
OkFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
pub struct OkFlowChain<Head, Next, InputOk>
where
Head: OkFlow<InputOk>,
Next: OkFlow<Head::OutputOk>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputOk>,
}
impl<Head, Next, InputOk> OkFlow<InputOk> for OkFlowChain<Head, Next, InputOk>
where
Head: OkFlow<InputOk>,
Next: OkFlow<Head::OutputOk>,
{
type OutputOk = Next::OutputOk;
fn apply_ok(&self, input_ok: InputOk) -> Self::OutputOk {
let result = self.head.apply_ok(input_ok);
self.next.apply_ok(result)
}
}
impl<Head, Next, InputOk> Clone for OkFlowChain<Head, Next, InputOk>
where
Head: OkFlow<InputOk> + Clone,
Next: OkFlow<Head::OutputOk> + Clone,
{
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
next: self.next.clone(),
_phantom: PhantomData,
}
}
}
impl<Head, Next, InputOk> Copy for OkFlowChain<Head, Next, InputOk>
where
Head: OkFlow<InputOk> + Copy,
Next: OkFlow<Head::OutputOk> + Copy,
{
}