use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FaultSeverity {
ItemSkipped,
StageFailed,
}
impl FaultSeverity {
pub fn label(self) -> &'static str {
match self {
Self::ItemSkipped => "warning",
Self::StageFailed => "error",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CollectionFault {
pub severity: FaultSeverity,
pub message: String,
}
impl CollectionFault {
pub fn item_skipped(message: impl Into<String>) -> Self {
Self {
severity: FaultSeverity::ItemSkipped,
message: message.into(),
}
}
pub fn stage_failed(message: impl Into<String>) -> Self {
Self {
severity: FaultSeverity::StageFailed,
message: message.into(),
}
}
pub fn is_stage_failure(&self) -> bool {
self.severity == FaultSeverity::StageFailed
}
}
impl fmt::Display for CollectionFault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl crate::collect::collector::CollectionStats {
pub fn fail_stage(&mut self, message: impl Into<String>) {
self.errors.push(CollectionFault::stage_failed(message));
}
pub fn skip_item(&mut self, message: impl Into<String>) {
self.errors.push(CollectionFault::item_skipped(message));
}
pub fn stage_failures(&self) -> Vec<&CollectionFault> {
self.errors
.iter()
.filter(|e| e.is_stage_failure())
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_renders_the_message_alone() {
let fault = CollectionFault::stage_failed("Linear: store work_items failed: disk full");
assert_eq!(
fault.to_string(),
"Linear: store work_items failed: disk full",
"existing `{{e}}` call sites must print what they always printed"
);
}
#[test]
fn stage_failed_and_item_skipped_carry_distinct_labels() {
assert!(CollectionFault::stage_failed("x").is_stage_failure());
assert!(!CollectionFault::item_skipped("x").is_stage_failure());
assert_eq!(FaultSeverity::StageFailed.label(), "error");
assert_eq!(FaultSeverity::ItemSkipped.label(), "warning");
}
}