use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum XmlError {
ParseError {
pos: usize,
message: String,
},
WriteError {
context: String,
message: String,
},
RecursionLimitExceeded {
max: usize,
current: usize,
},
ListSizeLimitExceeded {
max: usize,
current: usize,
},
StringLengthLimitExceeded {
max: usize,
current: usize,
},
InvalidValue {
message: String,
},
Utf8Error {
message: String,
},
StructureError {
message: String,
},
}
impl fmt::Display for XmlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
XmlError::ParseError { pos, message } => {
write!(f, "XML parse error at position {}: {}", pos, message)
}
XmlError::WriteError { context, message } => {
write!(f, "Failed to write {}: {}", context, message)
}
XmlError::RecursionLimitExceeded { max, current } => {
write!(
f,
"XML recursion depth exceeded (max: {}, found: {})",
max, current
)
}
XmlError::ListSizeLimitExceeded { max, current } => {
write!(
f,
"List size exceeded maximum (max: {}, found: {})",
max, current
)
}
XmlError::StringLengthLimitExceeded { max, current } => {
write!(
f,
"String length exceeded maximum (max: {}, found: {})",
max, current
)
}
XmlError::InvalidValue { message } => {
write!(f, "Invalid value: {}", message)
}
XmlError::Utf8Error { message } => {
write!(f, "UTF-8 encoding error: {}", message)
}
XmlError::StructureError { message } => {
write!(f, "Invalid XML structure: {}", message)
}
}
}
}
impl std::error::Error for XmlError {}
impl From<quick_xml::Error> for XmlError {
fn from(err: quick_xml::Error) -> Self {
XmlError::ParseError {
pos: 0, message: err.to_string(),
}
}
}
impl From<std::str::Utf8Error> for XmlError {
fn from(err: std::str::Utf8Error) -> Self {
XmlError::Utf8Error {
message: err.to_string(),
}
}
}
impl From<std::string::FromUtf8Error> for XmlError {
fn from(err: std::string::FromUtf8Error) -> Self {
XmlError::Utf8Error {
message: err.to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_error_display() {
let err = XmlError::ParseError {
pos: 42,
message: "unexpected end of file".to_string(),
};
assert_eq!(
err.to_string(),
"XML parse error at position 42: unexpected end of file"
);
}
#[test]
fn test_write_error_display() {
let err = XmlError::WriteError {
context: "root element".to_string(),
message: "I/O error".to_string(),
};
assert_eq!(err.to_string(), "Failed to write root element: I/O error");
}
#[test]
fn test_recursion_limit_display() {
let err = XmlError::RecursionLimitExceeded {
max: 100,
current: 101,
};
assert_eq!(
err.to_string(),
"XML recursion depth exceeded (max: 100, found: 101)"
);
}
#[test]
fn test_list_size_limit_display() {
let err = XmlError::ListSizeLimitExceeded {
max: 100000,
current: 100001,
};
assert_eq!(
err.to_string(),
"List size exceeded maximum (max: 100000, found: 100001)"
);
}
#[test]
fn test_string_length_limit_display() {
let err = XmlError::StringLengthLimitExceeded {
max: 1000000,
current: 1000001,
};
assert_eq!(
err.to_string(),
"String length exceeded maximum (max: 1000000, found: 1000001)"
);
}
#[test]
fn test_invalid_value_display() {
let err = XmlError::InvalidValue {
message: "expected number".to_string(),
};
assert_eq!(err.to_string(), "Invalid value: expected number");
}
#[test]
fn test_utf8_error_display() {
let err = XmlError::Utf8Error {
message: "invalid UTF-8 sequence".to_string(),
};
assert_eq!(err.to_string(), "UTF-8 encoding error: invalid UTF-8 sequence");
}
#[test]
fn test_structure_error_display() {
let err = XmlError::StructureError {
message: "missing required element".to_string(),
};
assert_eq!(
err.to_string(),
"Invalid XML structure: missing required element"
);
}
#[test]
fn test_error_trait() {
let err = XmlError::ParseError {
pos: 0,
message: "test".to_string(),
};
let _: &dyn std::error::Error = &err;
}
#[test]
fn test_clone() {
let err = XmlError::RecursionLimitExceeded {
max: 100,
current: 101,
};
let cloned = err.clone();
assert_eq!(err, cloned);
}
#[test]
fn test_debug() {
let err = XmlError::InvalidValue {
message: "test".to_string(),
};
let debug = format!("{:?}", err);
assert!(debug.contains("InvalidValue"));
assert!(debug.contains("test"));
}
}