1use crate::error::{ErrorCode, FixSuggestion, SourceLocation};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum SecuritySeverity {
10 Critical,
11 High,
12 Medium,
13 Low,
14 Info,
15}
16
17#[derive(Debug, Clone)]
19pub struct SecurityIssue {
20 pub severity: SecuritySeverity,
21 pub code: ErrorCode,
22 pub message: String,
23 pub location: SourceLocation,
24 pub suggestion: Option<FixSuggestion>,
25}
26
27impl SecurityIssue {
28 pub fn critical(code: ErrorCode, msg: impl Into<String>, loc: SourceLocation) -> Self {
29 Self {
30 severity: SecuritySeverity::Critical,
31 code,
32 message: msg.into(),
33 location: loc,
34 suggestion: None,
35 }
36 }
37
38 pub fn high(code: ErrorCode, msg: impl Into<String>, loc: SourceLocation) -> Self {
39 Self {
40 severity: SecuritySeverity::High,
41 code,
42 message: msg.into(),
43 location: loc,
44 suggestion: None,
45 }
46 }
47
48 pub fn with_suggestion(mut self, s: FixSuggestion) -> Self {
49 self.suggestion = Some(s);
50 self
51 }
52}
53
54#[derive(Default)]
56pub struct SecurityChecker {
57 issues: Vec<SecurityIssue>,
58}
59
60impl SecurityChecker {
61 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn add_issue(&mut self, issue: SecurityIssue) {
66 self.issues.push(issue);
67 }
68
69 pub fn issues(&self) -> &[SecurityIssue] {
70 &self.issues
71 }
72
73 pub fn has_critical(&self) -> bool {
74 self.issues
75 .iter()
76 .any(|i| i.severity == SecuritySeverity::Critical)
77 }
78
79 pub fn has_high(&self) -> bool {
80 self.issues
81 .iter()
82 .any(|i| i.severity == SecuritySeverity::High)
83 }
84
85 pub fn count_by_severity(&self, sev: SecuritySeverity) -> usize {
86 self.issues.iter().filter(|i| i.severity == sev).count()
87 }
88
89 pub fn clear(&mut self) {
90 self.issues.clear();
91 }
92}