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