cc_audit/scanner/
error.rs1use std::path::PathBuf;
4use thiserror::Error;
5
6#[derive(Error, Debug)]
8pub enum ScanError {
9 #[error("File not found: {0}")]
10 FileNotFound(PathBuf),
11
12 #[error("Path is not a file: {0}")]
13 NotAFile(PathBuf),
14
15 #[error("Path is not a directory: {0}")]
16 NotADirectory(PathBuf),
17
18 #[error("Failed to read file: {path}")]
19 ReadError {
20 path: PathBuf,
21 #[source]
22 source: std::io::Error,
23 },
24
25 #[error("Failed to parse YAML in {path}")]
26 YamlParseError {
27 path: PathBuf,
28 #[source]
29 source: serde_yaml::Error,
30 },
31
32 #[error("Failed to parse JSON in {path}")]
33 JsonParseError {
34 path: PathBuf,
35 #[source]
36 source: serde_json::Error,
37 },
38
39 #[error("Invalid format in {path}: {message}")]
40 InvalidFormat { path: PathBuf, message: String },
41
42 #[error("Regex compilation error: {0}")]
43 RegexError(#[from] regex::Error),
44}
45
46impl ScanError {
47 pub fn file_not_found(path: impl Into<PathBuf>) -> Self {
49 Self::FileNotFound(path.into())
50 }
51
52 pub fn not_a_directory(path: impl Into<PathBuf>) -> Self {
54 Self::NotADirectory(path.into())
55 }
56
57 pub fn read_error(path: impl Into<PathBuf>, source: std::io::Error) -> Self {
59 Self::ReadError {
60 path: path.into(),
61 source,
62 }
63 }
64
65 pub fn yaml_error(path: impl Into<PathBuf>, source: serde_yaml::Error) -> Self {
67 Self::YamlParseError {
68 path: path.into(),
69 source,
70 }
71 }
72
73 pub fn json_error(path: impl Into<PathBuf>, source: serde_json::Error) -> Self {
75 Self::JsonParseError {
76 path: path.into(),
77 source,
78 }
79 }
80
81 pub fn invalid_format(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
83 Self::InvalidFormat {
84 path: path.into(),
85 message: message.into(),
86 }
87 }
88}
89
90pub type ScanResult<T> = std::result::Result<T, ScanError>;
92
93impl From<ScanError> for crate::error::AuditError {
95 fn from(err: ScanError) -> Self {
96 match err {
97 ScanError::FileNotFound(path) => {
98 crate::error::AuditError::FileNotFound(path.display().to_string())
99 }
100 ScanError::NotAFile(path) => {
101 crate::error::AuditError::NotADirectory(path.display().to_string())
102 }
103 ScanError::NotADirectory(path) => {
104 crate::error::AuditError::NotADirectory(path.display().to_string())
105 }
106 ScanError::ReadError { path, source } => crate::error::AuditError::ReadError {
107 path: path.display().to_string(),
108 source,
109 },
110 ScanError::YamlParseError { path, source } => {
111 crate::error::AuditError::YamlParseError {
112 path: path.display().to_string(),
113 source,
114 }
115 }
116 ScanError::JsonParseError { path, .. } => crate::error::AuditError::ParseError {
117 path: path.display().to_string(),
118 message: "JSON parse error".to_string(),
119 },
120 ScanError::InvalidFormat { path, message } => crate::error::AuditError::ParseError {
121 path: path.display().to_string(),
122 message,
123 },
124 ScanError::RegexError(e) => crate::error::AuditError::RegexError(e),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use std::path::Path;
133
134 #[test]
135 fn test_file_not_found() {
136 let err = ScanError::file_not_found("/path/to/file");
137 assert!(err.to_string().contains("/path/to/file"));
138 }
139
140 #[test]
141 fn test_not_a_directory() {
142 let err = ScanError::not_a_directory(Path::new("/path/to/file"));
143 assert!(err.to_string().contains("/path/to/file"));
144 }
145
146 #[test]
147 fn test_read_error() {
148 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "not found");
149 let err = ScanError::read_error("/path/to/file", io_err);
150 assert!(err.to_string().contains("/path/to/file"));
151 }
152
153 #[test]
154 fn test_invalid_format() {
155 let err = ScanError::invalid_format("/path/to/file", "missing field");
156 assert!(err.to_string().contains("/path/to/file"));
157 assert!(err.to_string().contains("missing field"));
158 }
159
160 #[test]
161 fn test_conversion_to_audit_error() {
162 let scan_err = ScanError::file_not_found("/test/path");
163 let audit_err: crate::error::AuditError = scan_err.into();
164 assert!(audit_err.to_string().contains("/test/path"));
165 }
166}