1
2 use std::io;
3 use std::borrow::Cow;
4 use std::fmt;
5 use std::error;
6 use std::str;
7
8 use util;
9 use common::{Position, TextPosition};
10
11 #[derive(Debug)]
12 pub enum ErrorKind {
13 Syntax(Cow<'static, str>),
14 Io(io::Error),
15 Utf8(str::Utf8Error),
16 UnexpectedEof,
17 }
18
19 /// An XML parsing error.
20 ///
21 /// Consists of a 2D position in a document and a textual message describing the error.
22 #[derive(Clone, PartialEq, Eq, Debug)]
23 pub struct Error {
24 pos: TextPosition,
25 kind: ErrorKind,
26 }
27
28 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result29 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30 write!(f, "{} {}", self.pos, self.msg())
31 }
32 }
33
34 impl Position for Error {
35 #[inline]
position(&self) -> TextPosition36 fn position(&self) -> TextPosition { self.pos }
37 }
38
39 impl Error {
40 /// Returns a reference to a message which is contained inside this error.
41 #[inline]
msg(&self) -> &str42 pub fn msg(&self) -> &str {
43 use self::ErrorKind::*;
44 match self.kind {
45 UnexpectedEof => &"Unexpected EOF",
46 Utf8(ref reason) => error_description(reason),
47 Io(ref io_error) => error_description(io_error),
48 Syntax(ref msg) => msg.as_ref(),
49 }
50 }
51
kind(&self) -> &ErrorKind52 pub fn kind(&self) -> &ErrorKind { &self.kind }
53 }
54
55 impl error::Error for Error {
56 #[inline]
description(&self) -> &str57 fn description(&self) -> &str { self.msg() }
58 }
59
60 impl<'a, P, M> From<(&'a P, M)> for Error where P: Position, M: Into<Cow<'static, str>> {
from(orig: (&'a P, M)) -> Self61 fn from(orig: (&'a P, M)) -> Self {
62 Error{
63 pos: orig.0.position(),
64 kind: ErrorKind::Syntax(orig.1.into())
65 }
66 }
67 }
68
69 impl From<util::CharReadError> for Error {
from(e: util::CharReadError) -> Self70 fn from(e: util::CharReadError) -> Self {
71 use util::CharReadError::*;
72 Error{
73 pos: TextPosition::new(),
74 kind: match e {
75 UnexpectedEof => ErrorKind::UnexpectedEof,
76 Utf8(reason) => ErrorKind::Utf8(reason),
77 Io(io_error) => ErrorKind::Io(io_error),
78 }
79 }
80 }
81 }
82
83 impl From<io::Error> for Error {
from(e: io::Error) -> Self84 fn from(e: io::Error) -> Self {
85 Error {
86 pos: TextPosition::new(),
87 kind: ErrorKind::Io(e),
88 }
89 }
90 }
91
92 impl Clone for ErrorKind {
clone(&self) -> Self93 fn clone(&self) -> Self {
94 use self::ErrorKind::*;
95 match *self {
96 UnexpectedEof => UnexpectedEof,
97 Utf8(ref reason) => Utf8(reason.clone()),
98 Io(ref io_error) => Io(io::Error::new(io_error.kind(), error_description(io_error))),
99 Syntax(ref msg) => Syntax(msg.clone()),
100 }
101 }
102 }
103 impl PartialEq for ErrorKind {
eq(&self, other: &ErrorKind) -> bool104 fn eq(&self, other: &ErrorKind) -> bool {
105 use self::ErrorKind::*;
106 match (self, other) {
107 (&UnexpectedEof, &UnexpectedEof) => true,
108 (&Utf8(ref left), &Utf8(ref right)) => left == right,
109 (&Io(ref left), &Io(ref right)) =>
110 left.kind() == right.kind() &&
111 error_description(left) == error_description(right),
112 (&Syntax(ref left), &Syntax(ref right)) =>
113 left == right,
114
115 (_, _) => false,
116 }
117 }
118 }
119 impl Eq for ErrorKind {}
120
error_description(e: &error::Error) -> &str121 fn error_description(e: &error::Error) -> &str { e.description() }
122