Skip to main content

nessus_parser/
error.rs

1//! Parse errors.
2
3/// Errors returned while parsing Nessus XML into typed structures.
4#[derive(Debug, Clone)]
5pub enum FormatError {
6    /// A required XML attribute was not present.
7    MissingAttribute(&'static str),
8    /// A required XML tag was not present.
9    MissingTag(&'static str),
10    /// A tag expected to appear once was repeated.
11    RepeatedTag(&'static str),
12    /// A value had an unexpected shape.
13    UnexpectedFormat(&'static str),
14    /// An XML node kind was not expected at this position.
15    UnexpectedNodeKind,
16    /// Non-empty text was found where no text content is allowed.
17    UnexpectedText(Box<str>),
18    /// An unknown XML attribute was encountered.
19    UnexpectedXmlAttribute(Box<str>),
20    /// The root tag does not match `NessusClientData_v2`.
21    UnsupportedVersion,
22    /// Failed to parse an integer value.
23    ParseInt(std::num::ParseIntError),
24    /// Failed to parse XML.
25    Xml(Box<roxmltree::Error>),
26    /// Failed to parse date/time data via `jiff`.
27    Jiff(jiff::Error),
28    /// Failed to parse an IP address.
29    IpAddrParse(std::net::AddrParseError),
30    /// Failed to parse a boolean value.
31    BoolParse(std::str::ParseBoolError),
32    /// An unexpected XML node/tag was encountered.
33    UnexpectedNode(Box<str>),
34    /// A ping-method line in plugin output is not recognized.
35    UnexpectedPingMethod(Box<str>),
36    /// A dead-host reason in plugin output is not recognized.
37    UnexpectedDeadHostReason(Box<str>),
38    /// A TCP reply suffix in plugin output is not recognized.
39    UnexpectedPingTcpResponse(Box<str>),
40    /// Ping plugin output does not match any recognized format.
41    UnexpectedPingFormat(Box<str>),
42    /// A protocol string was not one of `tcp`, `udp`, or `icmp`.
43    UnexpectedProtocol(Box<str>),
44    /// A MAC address could not be parsed from `XX:XX:XX:XX:XX:XX`.
45    MacAddressParse,
46    /// A plugin type string/value was not recognized.
47    UnexpectedPluginType(Box<str>),
48    /// A severity string/value was not recognized.
49    UnexpectedLevel(Box<str>),
50    /// A plugin item required `plugin_output` but it was missing.
51    MissingPluginOutput,
52}
53
54impl From<std::str::ParseBoolError> for FormatError {
55    fn from(err: std::str::ParseBoolError) -> Self {
56        Self::BoolParse(err)
57    }
58}
59
60impl From<std::net::AddrParseError> for FormatError {
61    fn from(err: std::net::AddrParseError) -> Self {
62        Self::IpAddrParse(err)
63    }
64}
65
66impl From<std::num::ParseIntError> for FormatError {
67    fn from(err: std::num::ParseIntError) -> Self {
68        Self::ParseInt(err)
69    }
70}
71
72impl From<roxmltree::Error> for FormatError {
73    fn from(err: roxmltree::Error) -> Self {
74        Self::Xml(Box::from(err))
75    }
76}
77
78impl From<jiff::Error> for FormatError {
79    fn from(err: jiff::Error) -> Self {
80        Self::Jiff(err)
81    }
82}
83
84impl std::fmt::Display for FormatError {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        match self {
87            Self::MissingAttribute(attr) => {
88                write!(f, "Missing attribute: {attr}")
89            }
90            Self::MissingTag(tag) => {
91                write!(f, "Missing tag: {tag}")
92            }
93            Self::RepeatedTag(tag) => {
94                write!(f, "Repeated tag: {tag}")
95            }
96            Self::UnexpectedFormat(s) => {
97                write!(f, "Unexpected format: {s}")
98            }
99            Self::UnexpectedNodeKind => {
100                write!(f, "Unexpected NodeKind")
101            }
102            Self::UnexpectedText(s) => {
103                write!(f, "Unexpected text: {s}")
104            }
105            Self::UnexpectedNode(s) => {
106                write!(f, "Unexpected node: {s}")
107            }
108            Self::UnexpectedXmlAttribute(s) => {
109                write!(f, "Unexpected XML attributes: {s}")
110            }
111            Self::UnsupportedVersion => write!(f, "Unsupported version"),
112            Self::UnexpectedPingMethod(s) => write!(f, "Unexpected ping method: {s}"),
113            Self::UnexpectedDeadHostReason(s) => write!(f, "Unexpected dead host reason: {s}"),
114            Self::UnexpectedPingTcpResponse(s) => write!(f, "Unexpected ping TCP response: {s}"),
115            Self::UnexpectedPingFormat(s) => write!(f, "Unexpected ping format: {s}"),
116            Self::UnexpectedProtocol(s) => write!(f, "Unexpected protocol: {s}"),
117            Self::UnexpectedPluginType(s) => write!(f, "Unexpected plugin type: {s}"),
118            Self::UnexpectedLevel(s) => write!(f, "Unexpected level: {s}"),
119            Self::MissingPluginOutput => write!(f, "Missing plugin output"),
120            Self::MacAddressParse => write!(f, "Can't parse MAC address"),
121            Self::ParseInt(err) => write!(f, "{err}"),
122            Self::Xml(err) => write!(f, "{err}"),
123            Self::Jiff(err) => write!(f, "{err}"),
124            Self::IpAddrParse(err) => write!(f, "{err}"),
125            Self::BoolParse(err) => write!(f, "{err}"),
126        }
127    }
128}
129
130impl std::error::Error for FormatError {
131    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
132        match self {
133            Self::ParseInt(err) => Some(err),
134            Self::Xml(err) => Some(err),
135            Self::Jiff(err) => Some(err),
136            Self::IpAddrParse(err) => Some(err),
137            Self::BoolParse(err) => Some(err),
138            Self::MissingAttribute(_)
139            | Self::MissingTag(_)
140            | Self::RepeatedTag(_)
141            | Self::UnexpectedFormat(_)
142            | Self::UnexpectedNodeKind
143            | Self::UnexpectedNode(_)
144            | Self::UnexpectedText(_)
145            | Self::UnexpectedXmlAttribute(_)
146            | Self::UnsupportedVersion
147            | Self::UnexpectedPingMethod(_)
148            | Self::UnexpectedDeadHostReason(_)
149            | Self::UnexpectedPingTcpResponse(_)
150            | Self::UnexpectedPingFormat(_)
151            | Self::UnexpectedProtocol(_)
152            | Self::UnexpectedPluginType(_)
153            | Self::UnexpectedLevel(_)
154            | Self::MissingPluginOutput
155            | Self::MacAddressParse => None,
156        }
157    }
158}