use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PipelineStage {
Input,
Config,
Discovery,
Parsing,
Detection,
Aggregation,
Output,
}
impl PipelineStage {
pub fn next(&self) -> Option<Self> {
match self {
Self::Input => Some(Self::Config),
Self::Config => Some(Self::Discovery),
Self::Discovery => Some(Self::Parsing),
Self::Parsing => Some(Self::Detection),
Self::Detection => Some(Self::Aggregation),
Self::Aggregation => Some(Self::Output),
Self::Output => None,
}
}
pub fn name(&self) -> &'static str {
match self {
Self::Input => "input",
Self::Config => "config",
Self::Discovery => "discovery",
Self::Parsing => "parsing",
Self::Detection => "detection",
Self::Aggregation => "aggregation",
Self::Output => "output",
}
}
}
pub struct Pipeline {
current_stage: PipelineStage,
}
impl Pipeline {
pub fn new() -> Self {
Self {
current_stage: PipelineStage::Input,
}
}
pub fn current_stage(&self) -> PipelineStage {
self.current_stage
}
pub fn advance(&mut self) -> Result<bool> {
if let Some(next) = self.current_stage.next() {
self.current_stage = next;
Ok(true)
} else {
Ok(false)
}
}
pub fn is_complete(&self) -> bool {
self.current_stage == PipelineStage::Output
}
}
impl Default for Pipeline {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pipeline_stages() {
let mut pipeline = Pipeline::new();
assert_eq!(pipeline.current_stage(), PipelineStage::Input);
assert!(!pipeline.is_complete());
while pipeline.advance().unwrap() {}
assert!(pipeline.is_complete());
assert_eq!(pipeline.current_stage(), PipelineStage::Output);
}
#[test]
fn test_stage_names() {
assert_eq!(PipelineStage::Input.name(), "input");
assert_eq!(PipelineStage::Detection.name(), "detection");
assert_eq!(PipelineStage::Output.name(), "output");
}
#[test]
fn test_all_stage_names() {
assert_eq!(PipelineStage::Input.name(), "input");
assert_eq!(PipelineStage::Config.name(), "config");
assert_eq!(PipelineStage::Discovery.name(), "discovery");
assert_eq!(PipelineStage::Parsing.name(), "parsing");
assert_eq!(PipelineStage::Detection.name(), "detection");
assert_eq!(PipelineStage::Aggregation.name(), "aggregation");
assert_eq!(PipelineStage::Output.name(), "output");
}
#[test]
fn test_stage_next_chain() {
assert_eq!(PipelineStage::Input.next(), Some(PipelineStage::Config));
assert_eq!(PipelineStage::Config.next(), Some(PipelineStage::Discovery));
assert_eq!(
PipelineStage::Discovery.next(),
Some(PipelineStage::Parsing)
);
assert_eq!(
PipelineStage::Parsing.next(),
Some(PipelineStage::Detection)
);
assert_eq!(
PipelineStage::Detection.next(),
Some(PipelineStage::Aggregation)
);
assert_eq!(
PipelineStage::Aggregation.next(),
Some(PipelineStage::Output)
);
assert_eq!(PipelineStage::Output.next(), None);
}
#[test]
fn test_pipeline_advance_returns_false_at_end() {
let mut pipeline = Pipeline::new();
while pipeline.advance().unwrap() {}
assert_eq!(pipeline.current_stage(), PipelineStage::Output);
let result = pipeline.advance().unwrap();
assert!(!result);
assert_eq!(pipeline.current_stage(), PipelineStage::Output);
}
#[test]
fn test_pipeline_multiple_advances() {
let mut pipeline = Pipeline::new();
assert_eq!(pipeline.current_stage(), PipelineStage::Input);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Config);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Discovery);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Parsing);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Detection);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Aggregation);
assert!(pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Output);
assert!(pipeline.is_complete());
assert!(!pipeline.advance().unwrap());
assert_eq!(pipeline.current_stage(), PipelineStage::Output);
}
}