1use std::error::Error as StdError;
2use std::fmt;
3use std::result::Result as StdResult;
4
5pub(crate) type Result<T = ()> = StdResult<T, Box<Error>>;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub enum ErrorKind {
9 MissingRootElement,
10 UnclosedRootElement,
11 UnexpectedCloseElement,
12 TooManyNodes,
13 TooManyAttributes,
14 TooManyNamespaces,
15 TooManyEntityReferences,
16 TooManyStrings,
17 ExpectedLiteral(&'static str),
18 ExpectedSpace,
19 ExpectedQuote,
20 ExpectedEnd,
21 InvalidSyntax,
22 InvalidName,
23 InvalidReference(String),
24 UnknownNamespace(String),
25 UnknownEntity(String),
26}
27
28impl<T> From<ErrorKind> for Result<T> {
29 #[cold]
30 #[inline(never)]
31 fn from(kind: ErrorKind) -> Self {
32 Err(Box::new(Error { kind, pos: None }))
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct Error {
38 pub kind: ErrorKind,
39 pub pos: Option<(usize, usize)>,
40}
41
42impl StdError for Error {}
43
44impl fmt::Display for Error {
45 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match &self.kind {
47 ErrorKind::MissingRootElement => fmt.write_str("missing root element")?,
48 ErrorKind::UnclosedRootElement => fmt.write_str("unclosed root element")?,
49 ErrorKind::UnexpectedCloseElement => fmt.write_str("unexpected close element")?,
50 ErrorKind::TooManyNodes => fmt.write_str("too many nodes")?,
51 ErrorKind::TooManyAttributes => fmt.write_str("too many attributes")?,
52 ErrorKind::TooManyNamespaces => fmt.write_str("too many namespaces")?,
53 ErrorKind::TooManyEntityReferences => fmt.write_str("too many entity references")?,
54 ErrorKind::TooManyStrings => fmt.write_str("too many strings")?,
55 ErrorKind::ExpectedLiteral(literal) => write!(fmt, "expected literal `{literal}`")?,
56 ErrorKind::ExpectedSpace => fmt.write_str("expected whitespace")?,
57 ErrorKind::ExpectedQuote => fmt.write_str("expected single or double quote")?,
58 ErrorKind::ExpectedEnd => fmt.write_str("expected end")?,
59 ErrorKind::InvalidSyntax => fmt.write_str("invalid syntax")?,
60 ErrorKind::InvalidName => fmt.write_str("invalid name")?,
61 ErrorKind::InvalidReference(value) => write!(fmt, "invalid reference `{value}`")?,
62 ErrorKind::UnknownNamespace(prefix) => write!(fmt, "unknown namespace `{prefix}`")?,
63 ErrorKind::UnknownEntity(name) => write!(fmt, "unknown entity `{name}`")?,
64 }
65
66 if let Some((line, pos)) = self.pos {
67 write!(fmt, " at {line}:{pos}")?;
68 }
69
70 Ok(())
71 }
72}