1use crate::interface::FamilyParseError;
2use std::error::Error;
3use std::fmt;
4use std::io;
5
6#[derive(Debug)]
10pub enum NetworkInterfacesError {
11 Io(io::Error),
13 Parser(ParserError),
15 FamilyParse(FamilyParseError),
17 FileModified,
19 Other(String),
21}
22
23impl fmt::Display for NetworkInterfacesError {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 match self {
26 NetworkInterfacesError::Io(err) => write!(f, "I/O error: {}", err),
27 NetworkInterfacesError::Parser(err) => write!(f, "Parser error: {}", err),
28 NetworkInterfacesError::FamilyParse(err) => write!(f, "Family parse error: {}", err),
29 NetworkInterfacesError::FileModified => write!(
30 f,
31 "The interfaces file has been modified on disk since it was last loaded."
32 ),
33 NetworkInterfacesError::Other(msg) => write!(f, "Error: {}", msg),
34 }
35 }
36}
37
38impl Error for NetworkInterfacesError {
39 fn source(&self) -> Option<&(dyn Error + 'static)> {
40 match self {
41 NetworkInterfacesError::Io(err) => Some(err),
42 NetworkInterfacesError::Parser(err) => Some(err),
43 NetworkInterfacesError::FamilyParse(err) => Some(err),
44 NetworkInterfacesError::FileModified => None,
45 NetworkInterfacesError::Other(_) => None,
46 }
47 }
48}
49
50impl From<io::Error> for NetworkInterfacesError {
51 fn from(err: io::Error) -> Self {
52 NetworkInterfacesError::Io(err)
53 }
54}
55
56impl From<ParserError> for NetworkInterfacesError {
57 fn from(err: ParserError) -> Self {
58 NetworkInterfacesError::Parser(err)
59 }
60}
61
62impl From<FamilyParseError> for NetworkInterfacesError {
63 fn from(err: FamilyParseError) -> Self {
64 NetworkInterfacesError::FamilyParse(err)
65 }
66}
67
68#[derive(Debug, Clone)]
70pub struct ParserError {
71 pub message: String,
73 pub line: Option<usize>,
75}
76
77impl ParserError {
78 pub fn new(message: impl Into<String>, line: usize) -> Self {
80 Self {
81 message: message.into(),
82 line: Some(line),
83 }
84 }
85
86 pub fn message(message: impl Into<String>) -> Self {
88 Self {
89 message: message.into(),
90 line: None,
91 }
92 }
93}
94
95impl fmt::Display for ParserError {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 if let Some(line) = self.line {
98 write!(f, "Parser error on line {}: {}", line, self.message)
99 } else {
100 write!(f, "Parser error: {}", self.message)
101 }
102 }
103}
104
105impl Error for ParserError {}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_parser_error_new() {
113 let err = ParserError::new("test error", 42);
114 assert_eq!(err.message, "test error");
115 assert_eq!(err.line, Some(42));
116 assert_eq!(err.to_string(), "Parser error on line 42: test error");
117 }
118
119 #[test]
120 fn test_parser_error_message() {
121 let err = ParserError::message("test error");
122 assert_eq!(err.message, "test error");
123 assert_eq!(err.line, None);
124 assert_eq!(err.to_string(), "Parser error: test error");
125 }
126
127 #[test]
128 fn test_network_interfaces_error_display() {
129 let io_err = NetworkInterfacesError::Io(io::Error::new(io::ErrorKind::NotFound, "file not found"));
130 assert!(io_err.to_string().contains("I/O error"));
131
132 let parser_err = NetworkInterfacesError::Parser(ParserError::new("bad syntax", 10));
133 assert!(parser_err.to_string().contains("Parser error"));
134
135 let file_mod = NetworkInterfacesError::FileModified;
136 assert!(file_mod.to_string().contains("modified on disk"));
137
138 let other = NetworkInterfacesError::Other("custom error".to_string());
139 assert!(other.to_string().contains("custom error"));
140 }
141
142 #[test]
143 fn test_error_conversions() {
144 let io_err = io::Error::new(io::ErrorKind::NotFound, "not found");
145 let converted: NetworkInterfacesError = io_err.into();
146 assert!(matches!(converted, NetworkInterfacesError::Io(_)));
147
148 let parser_err = ParserError::new("test", 1);
149 let converted: NetworkInterfacesError = parser_err.into();
150 assert!(matches!(converted, NetworkInterfacesError::Parser(_)));
151 }
152}