Skip to main content

security_rust/
result.rs

1// Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz
2
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum Severity {
7    Critical,
8    High,
9    Medium,
10    Low,
11}
12
13impl fmt::Display for Severity {
14    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15        match self {
16            Severity::Critical => write!(f, "CRITICAL"),
17            Severity::High => write!(f, "HIGH"),
18            Severity::Medium => write!(f, "MEDIUM"),
19            Severity::Low => write!(f, "LOW"),
20        }
21    }
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum AttackCategory {
26    Injection,
27    Protocol,
28    Data,
29    File,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct DetectionResult {
34    pub attack_type: String,
35    pub category: AttackCategory,
36    pub severity: Severity,
37    pub matched_pattern: String,
38    pub offset: usize,
39    pub message: String,
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    fn sample() -> DetectionResult {
47        DetectionResult {
48            attack_type: "xss".into(),
49            category: AttackCategory::Injection,
50            severity: Severity::Critical,
51            matched_pattern: "<script>".into(),
52            offset: 0,
53            message: "XSS detected".into(),
54        }
55    }
56
57    #[test]
58    fn severity_display_uppercase() {
59        assert_eq!(Severity::Critical.to_string(), "CRITICAL");
60        assert_eq!(Severity::High.to_string(), "HIGH");
61        assert_eq!(Severity::Medium.to_string(), "MEDIUM");
62        assert_eq!(Severity::Low.to_string(), "LOW");
63    }
64
65    #[test]
66    fn severity_equality() {
67        assert_eq!(Severity::Critical, Severity::Critical);
68        assert_ne!(Severity::Critical, Severity::High);
69        assert_ne!(Severity::Medium, Severity::Low);
70    }
71
72    #[test]
73    fn attack_category_equality() {
74        assert_eq!(AttackCategory::Injection, AttackCategory::Injection);
75        assert_ne!(AttackCategory::Injection, AttackCategory::Protocol);
76        assert_ne!(AttackCategory::Data, AttackCategory::File);
77    }
78
79    #[test]
80    fn detection_result_clone_and_equality() {
81        let a = sample();
82        assert_eq!(a, a.clone());
83    }
84
85    #[test]
86    fn detection_result_field_difference_changes_equality() {
87        let a = sample();
88        let b = DetectionResult {
89            severity: Severity::High,
90            ..a.clone()
91        };
92        assert_ne!(a, b);
93    }
94
95    #[test]
96    fn detection_result_debug_output() {
97        let dbg = format!("{:?}", sample());
98        assert!(dbg.contains("xss"));
99        assert!(dbg.contains("Injection"));
100        assert!(dbg.contains("CRITICAL") || dbg.contains("Critical"));
101    }
102}