term_guard/core/
level.rs

1//! Validation severity levels.
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6/// The severity level of a validation check.
7///
8/// This enum represents different levels of importance for validation checks,
9/// allowing users to categorize issues by their impact on data quality.
10/// Levels are ordered by severity: Error > Warning > Info.
11///
12/// # Usage Guidelines
13///
14/// - **Error**: Use for critical data quality issues that prevent processing
15///   - Missing required fields
16///   - Primary key violations
17///   - Data integrity violations
18///   - Invalid data formats that break downstream systems
19///
20/// - **Warning**: Use for issues that should be investigated but don't block processing
21///   - Data quality below expected thresholds
22///   - Unusual patterns or outliers
23///   - Missing optional but recommended fields
24///   - Performance-impacting data issues
25///
26/// - **Info**: Use for informational metrics and observations
27///   - Data distribution statistics
28///   - Row counts and cardinality metrics
29///   - Performance benchmarks
30///   - Data profiling results
31///
32/// # Examples
33///
34/// ```rust
35/// use term_guard::core::{Check, Level, ConstraintOptions};
36/// use term_guard::constraints::Assertion;
37///
38/// // Critical validations that must pass
39/// let critical_check = Check::builder("required_fields")
40///     .level(Level::Error)
41///     .completeness("transaction_id", ConstraintOptions::new().with_threshold(1.0))
42///     .completeness("amount", ConstraintOptions::new().with_threshold(1.0))
43///     .build();
44///
45/// // Quality checks that flag potential issues
46/// let quality_check = Check::builder("data_quality")
47///     .level(Level::Warning)
48///     .completeness("email", ConstraintOptions::new().with_threshold(0.95))
49///     .validates_regex("phone", r"^\+?\d{3}-\d{3}-\d{4}$", 0.90)
50///     .build();
51///
52/// // Informational metrics
53/// let metrics_check = Check::builder("data_profile")
54///     .level(Level::Info)
55///     .has_size(Assertion::GreaterThan(0.0))
56///     .has_mean("order_value", Assertion::Between(10.0, 1000.0))
57///     .build();
58/// ```
59///
60/// # Comparison
61///
62/// ```rust
63/// use term_guard::core::Level;
64///
65/// let critical_level = Level::Error;
66/// let warning_level = Level::Warning;
67/// let info_level = Level::Info;
68///
69/// assert!(critical_level > warning_level);
70/// assert!(warning_level > info_level);
71/// ```
72#[derive(
73    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default,
74)]
75#[serde(rename_all = "lowercase")]
76pub enum Level {
77    /// Informational level - Used for metrics and non-critical observations
78    Info = 0,
79    /// Warning level - Indicates potential issues that should be reviewed
80    #[default]
81    Warning = 1,
82    /// Error level - Indicates critical data quality issues that must be addressed
83    Error = 2,
84}
85
86impl Level {
87    /// Returns the string representation of the level.
88    pub fn as_str(&self) -> &'static str {
89        match self {
90            Level::Info => "info",
91            Level::Warning => "warning",
92            Level::Error => "error",
93        }
94    }
95
96    /// Checks if this level is at least as severe as another level.
97    ///
98    /// # Examples
99    ///
100    /// ```rust
101    /// use term_guard::core::Level;
102    ///
103    /// assert!(Level::Error.is_at_least(Level::Warning));
104    /// assert!(Level::Warning.is_at_least(Level::Warning));
105    /// assert!(!Level::Info.is_at_least(Level::Error));
106    /// ```
107    pub fn is_at_least(&self, other: Level) -> bool {
108        *self >= other
109    }
110}
111
112impl fmt::Display for Level {
113    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114        write!(f, "{}", self.as_str())
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_level_ordering() {
124        assert!(Level::Error > Level::Warning);
125        assert!(Level::Warning > Level::Info);
126        assert!(Level::Error > Level::Info);
127    }
128
129    #[test]
130    fn test_level_display() {
131        assert_eq!(Level::Info.to_string(), "info");
132        assert_eq!(Level::Warning.to_string(), "warning");
133        assert_eq!(Level::Error.to_string(), "error");
134    }
135
136    #[test]
137    fn test_level_is_at_least() {
138        assert!(Level::Error.is_at_least(Level::Info));
139        assert!(Level::Error.is_at_least(Level::Warning));
140        assert!(Level::Error.is_at_least(Level::Error));
141        assert!(Level::Warning.is_at_least(Level::Info));
142        assert!(Level::Warning.is_at_least(Level::Warning));
143        assert!(!Level::Warning.is_at_least(Level::Error));
144        assert!(Level::Info.is_at_least(Level::Info));
145        assert!(!Level::Info.is_at_least(Level::Warning));
146        assert!(!Level::Info.is_at_least(Level::Error));
147    }
148
149    #[test]
150    fn test_level_serde() {
151        let json = serde_json::to_string(&Level::Error).unwrap();
152        assert_eq!(json, "\"error\"");
153
154        let level: Level = serde_json::from_str("\"warning\"").unwrap();
155        assert_eq!(level, Level::Warning);
156    }
157}