use super::check::{CheckError, check_item, collect_all_outputs};
use super::id_set::IdSet;
use super::traits::{StepInfo, RunnableStep};
pub trait PipelineInfo {
fn for_each_info<'a>(&'a self, f: &mut dyn FnMut(&'a dyn StepInfo));
fn check(&self) -> Result<(), CheckError> {
self.check_with_capacity::<20>()
}
fn check_with_capacity<const N: usize>(&self) -> Result<(), CheckError> {
let mut all_produced = IdSet::<N>::new();
self.for_each_info(&mut |item| {
collect_all_outputs::<N>(item, &mut all_produced);
});
let mut produced = IdSet::<N>::new();
let mut consumed = IdSet::<N>::new();
let mut result = Ok(());
self.for_each_info(&mut |item| {
if result.is_ok() {
result = check_item::<N>(item, &all_produced, &mut produced, &mut consumed);
}
});
result
}
}
pub trait Steps<E>: PipelineInfo {
fn for_each_item<'a>(&'a self, f: &mut dyn FnMut(&'a dyn RunnableStep<E>));
}
macro_rules! impl_steps {
($($N:ident $idx:tt),+) => {
impl<$($N: StepInfo),+> PipelineInfo for ($($N,)+) {
fn for_each_info<'a>(&'a self, f: &mut dyn FnMut(&'a dyn StepInfo)) {
$(f(&self.$idx);)+
}
}
impl<E, $($N: RunnableStep<E>),+> Steps<E> for ($($N,)+) {
fn for_each_item<'a>(&'a self, f: &mut dyn FnMut(&'a dyn RunnableStep<E>)) {
$(f(&self.$idx);)+
}
}
};
}
impl_steps!(N0 0);
impl_steps!(N0 0, N1 1);
impl_steps!(N0 0, N1 1, N2 2);
impl_steps!(N0 0, N1 1, N2 2, N3 3);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4, N5 5);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4, N5 5, N6 6);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4, N5 5, N6 6, N7 7);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4, N5 5, N6 6, N7 7, N8 8);
impl_steps!(N0 0, N1 1, N2 2, N3 3, N4 4, N5 5, N6 6, N7 7, N8 8, N9 9);