use crate::Frame;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum FailureMode {
#[default]
Soft,
Hard,
Isolate,
}
#[derive(Debug, Clone)]
pub enum PipelineError {
MissingSource(&'static str),
KernelPanic(String),
}
impl std::fmt::Display for PipelineError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
PipelineError::MissingSource(name) => {
write!(f, "source '{}' was not pushed before compute()", name)
}
PipelineError::KernelPanic(msg) => {
write!(f, "kernel panicked: {}", msg)
}
}
}
}
impl std::error::Error for PipelineError {}
#[derive(Debug, Clone)]
pub struct PipelineSettings {
pub failure_mode: FailureMode,
pub na_threshold: f64,
pub purity_check: bool,
}
impl Default for PipelineSettings {
fn default() -> Self {
Self { failure_mode: FailureMode::Soft, na_threshold: 0.5, purity_check: false }
}
}
#[doc(hidden)]
pub trait PipelineImpl: Send {
fn push_sources(&mut self, frame: &Frame);
fn run(&mut self) -> Result<(), PipelineError>;
fn output(&self) -> &Frame;
fn drain_warnings(&mut self) -> Vec<String>;
fn drain_isolated_errors(&mut self) -> Vec<PipelineError>;
}
pub struct Pipeline {
inner: Box<dyn PipelineImpl>,
isolated_errors: Vec<PipelineError>,
}
impl Pipeline {
#[doc(hidden)]
pub fn new(inner: Box<dyn PipelineImpl>) -> Self {
Self { inner, isolated_errors: Vec::new() }
}
pub fn push(&mut self, frame: &Frame) -> &mut Self {
self.inner.push_sources(frame);
self
}
pub fn compute(&mut self) -> Result<(), PipelineError> {
self.isolated_errors.clear();
let result = self.inner.run();
self.isolated_errors.extend(self.inner.drain_isolated_errors());
result
}
pub fn output(&self) -> &Frame {
self.inner.output()
}
pub fn drain_warnings(&mut self) -> Vec<String> {
self.inner.drain_warnings()
}
pub fn errors(&self) -> &[PipelineError] {
&self.isolated_errors
}
}