1use std::path::PathBuf;
4
5pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("Configuration error: {0}")]
13 Config(String),
14
15 #[error("File error: {path} - {source}")]
17 File {
18 path: PathBuf,
19 #[source]
20 source: std::io::Error,
21 },
22
23 #[error("Parse error in {file}:{line}:{column}: {message}")]
25 Parse {
26 file: String,
27 line: usize,
28 column: usize,
29 message: String,
30 },
31
32 #[error("Validation error: {0}")]
34 Validation(String),
35
36 #[error("Watcher error: {0}")]
38 Watcher(String),
39
40 #[error("Wrapper error: {0}")]
42 Wrapper(String),
43
44 #[error("JSON error: {0}")]
46 Json(#[from] serde_json::Error),
47
48 #[error("TOML error: {0}")]
50 Toml(#[from] toml::de::Error),
51
52 #[error("Regex error: {0}")]
54 Regex(#[from] regex::Error),
55
56 #[error("{0}")]
58 Other(String),
59}
60
61impl Error {
62 pub fn file(path: impl Into<PathBuf>, source: std::io::Error) -> Self {
64 Self::File {
65 path: path.into(),
66 source,
67 }
68 }
69
70 pub fn parse(file: impl Into<String>, line: usize, column: usize, message: impl Into<String>) -> Self {
72 Self::Parse {
73 file: file.into(),
74 line,
75 column,
76 message: message.into(),
77 }
78 }
79
80 pub fn validation(msg: impl Into<String>) -> Self {
82 Self::Validation(msg.into())
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_error_display() {
92 let err = Error::validation("test error");
93 assert_eq!(err.to_string(), "Validation error: test error");
94 }
95
96 #[test]
97 fn test_error_config() {
98 let err = Error::Config("invalid config".to_string());
99 assert_eq!(err.to_string(), "Configuration error: invalid config");
100 }
101
102 #[test]
103 fn test_error_file() {
104 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
105 let err = Error::file("/path/to/file", io_err);
106 assert!(err.to_string().contains("File error"));
107 assert!(err.to_string().contains("/path/to/file"));
108 }
109
110 #[test]
111 fn test_error_parse() {
112 let err = Error::parse("test.js", 10, 5, "unexpected token");
113 assert_eq!(err.to_string(), "Parse error in test.js:10:5: unexpected token");
114 }
115
116 #[test]
117 fn test_error_validation() {
118 let err = Error::validation("invalid input");
119 assert_eq!(err.to_string(), "Validation error: invalid input");
120 }
121
122 #[test]
123 fn test_error_watcher() {
124 let err = Error::Watcher("watcher failed".to_string());
125 assert_eq!(err.to_string(), "Watcher error: watcher failed");
126 }
127
128 #[test]
129 fn test_error_wrapper() {
130 let err = Error::Wrapper("wrap failed".to_string());
131 assert_eq!(err.to_string(), "Wrapper error: wrap failed");
132 }
133
134 #[test]
135 fn test_error_other() {
136 let err = Error::Other("something happened".to_string());
137 assert_eq!(err.to_string(), "something happened");
138 }
139
140 #[test]
141 fn test_error_static_creation() {
142 assert!(matches!(Error::validation("test"), Error::Validation(_)));
143 assert!(matches!(Error::parse("", 0, 0, ""), Error::Parse { .. }));
144 }
145}