use std::collections::{HashMap, HashSet};
use super::sources::SourceStatus;
#[derive(Debug, Clone, Default)]
pub struct PipelineState {
pub applied_items: HashSet<String>,
pub rule_applied: HashSet<String>,
pub detection_item_applied: HashSet<String>,
pub state: HashMap<String, serde_json::Value>,
pub vars: HashMap<String, Vec<String>>,
pub source_status: HashMap<String, SourceStatus>,
}
impl PipelineState {
pub fn new(vars: HashMap<String, Vec<String>>) -> Self {
Self {
vars,
..Default::default()
}
}
pub fn mark_applied(&mut self, id: &str) {
self.applied_items.insert(id.to_string());
self.rule_applied.insert(id.to_string());
self.detection_item_applied.insert(id.to_string());
}
pub fn was_applied(&self, id: &str) -> bool {
self.applied_items.contains(id) || self.rule_applied.contains(id)
}
pub fn was_applied_to_detection_item(&self, id: &str) -> bool {
self.detection_item_applied.contains(id)
}
pub fn get_state(&self, key: &str) -> Option<&serde_json::Value> {
self.state.get(key)
}
pub fn set_state(&mut self, key: String, val: serde_json::Value) {
self.state.insert(key, val);
}
pub fn state_matches(&self, key: &str, val: &str) -> bool {
self.state
.get(key)
.and_then(|v| v.as_str())
.is_some_and(|s| s == val)
}
pub fn reset_rule(&mut self) {
self.rule_applied.clear();
self.detection_item_applied.clear();
}
pub fn reset_detection_item(&mut self) {
self.detection_item_applied.clear();
}
pub fn init_sources(&mut self, source_ids: impl IntoIterator<Item = String>) {
for id in source_ids {
self.source_status.insert(id, SourceStatus::Pending);
}
}
pub fn mark_source_resolved(&mut self, id: &str) {
self.source_status
.insert(id.to_string(), SourceStatus::Resolved);
}
pub fn mark_source_failed(&mut self, id: &str) {
self.source_status
.insert(id.to_string(), SourceStatus::Failed);
}
pub fn source_status(&self, id: &str) -> Option<SourceStatus> {
self.source_status.get(id).copied()
}
pub fn all_sources_resolved(&self) -> bool {
self.source_status
.values()
.all(|s| *s == SourceStatus::Resolved)
}
pub fn pending_sources(&self) -> Vec<&str> {
self.source_status
.iter()
.filter(|(_, status)| **status == SourceStatus::Pending)
.map(|(id, _)| id.as_str())
.collect()
}
}