use crate::channel::{self, Publisher, Subscribable, Subscriber};
use crate::pod::Pod;
use crate::wait::WaitStrategy;
use super::fan_out::FanOutBuilder;
use super::pipeline::Pipeline;
use super::{SharedState, DEFAULT_CAPACITY};
pub struct PipelineBuilder {
capacity: usize,
}
impl Default for PipelineBuilder {
fn default() -> Self {
Self::new()
}
}
impl PipelineBuilder {
pub fn new() -> Self {
PipelineBuilder {
capacity: DEFAULT_CAPACITY,
}
}
pub fn capacity(mut self, cap: usize) -> Self {
self.capacity = cap;
self
}
pub fn input<T: Pod>(self) -> (Publisher<T>, StageBuilder<T>) {
let (pub_, subs) = channel::channel::<T>(self.capacity);
let subscriber = subs.subscribe();
(
pub_,
StageBuilder {
subscriber,
subscribable: subs,
capacity: self.capacity,
state: SharedState::new(),
},
)
}
}
pub struct StageBuilder<T: Pod> {
pub(super) subscriber: Subscriber<T>,
pub(super) subscribable: Subscribable<T>,
pub(super) capacity: usize,
pub(super) state: SharedState,
}
impl<T: Pod> StageBuilder<T> {
pub fn then<U: Pod>(self, f: impl Fn(T) -> U + Send + 'static) -> StageBuilder<U> {
self.then_with(f, WaitStrategy::default())
}
pub fn then_with<U: Pod>(
mut self,
f: impl Fn(T) -> U + Send + 'static,
strategy: WaitStrategy,
) -> StageBuilder<U> {
let (next_sub, next_subs) =
self.state
.add_stage(self.subscriber, self.capacity, f, strategy);
StageBuilder {
subscriber: next_sub,
subscribable: next_subs,
capacity: self.capacity,
state: self.state,
}
}
pub fn fan_out<A, B>(
mut self,
fa: impl Fn(T) -> A + Send + 'static,
fb: impl Fn(T) -> B + Send + 'static,
) -> FanOutBuilder<A, B>
where
A: Pod,
B: Pod,
{
let input_b = self.subscribable.subscribe();
let strategy = WaitStrategy::default();
let (sub_a_out, subs_a) =
self.state
.add_stage(self.subscriber, self.capacity, fa, strategy);
let (sub_b_out, subs_b) = self.state.add_stage(input_b, self.capacity, fb, strategy);
FanOutBuilder {
sub_a: sub_a_out,
subs_a,
sub_b: sub_b_out,
subs_b,
capacity: self.capacity,
state: self.state,
}
}
pub fn build(self) -> (Subscriber<T>, Pipeline) {
(self.subscriber, self.state.into())
}
}