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<InputOk, Self, Next>
where
Self: Sized,
Next: OkFlow<Self::OutputOk>,
{
OkFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct OkFlowChain<InputOk, Head, Next>
where
Head: OkFlow<InputOk>,
Next: OkFlow<Head::OutputOk>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputOk>,
}
impl<InputOk, Head, Next> OkFlowChain<InputOk, Head, Next>
where
Head: OkFlow<InputOk>,
Next: OkFlow<Head::OutputOk>,
{
pub fn new(head: Head, next: Next) -> Self {
Self {
head,
next,
_phantom: PhantomData,
}
}
pub const fn new_const(head: Head, next: Next) -> Self {
Self {
head,
next,
_phantom: PhantomData,
}
}
}
impl<InputOk, Head, Next> OkFlow<InputOk> for OkFlowChain<InputOk, Head, Next>
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)
}
}