1use core::{fmt, str};
2#[cfg(feature = "std")]
3use std::error;
4
5#[allow(missing_docs)]
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
8pub enum Error {
9 InvalidDeclaration(StreamError, TextPos),
10 InvalidConditionalComment(StreamError, TextPos),
11 InvalidComment(StreamError, TextPos),
12 InvalidPI(StreamError, TextPos),
13 InvalidDoctype(StreamError, TextPos),
14 InvalidEntity(StreamError, TextPos),
15 InvalidElement(StreamError, TextPos),
16 InvalidAttribute(StreamError, TextPos),
17 InvalidCdata(StreamError, TextPos),
18 InvalidCharData(StreamError, TextPos),
19 UnknownToken(TextPos),
20}
21
22impl Error {
23 pub fn pos(&self) -> TextPos {
25 match *self {
26 Error::InvalidDeclaration(_, pos) => pos,
27 Error::InvalidConditionalComment(_, pos) => pos,
28 Error::InvalidComment(_, pos) => pos,
29 Error::InvalidPI(_, pos) => pos,
30 Error::InvalidDoctype(_, pos) => pos,
31 Error::InvalidEntity(_, pos) => pos,
32 Error::InvalidElement(_, pos) => pos,
33 Error::InvalidAttribute(_, pos) => pos,
34 Error::InvalidCdata(_, pos) => pos,
35 Error::InvalidCharData(_, pos) => pos,
36 Error::UnknownToken(pos) => pos,
37 }
38 }
39}
40
41impl fmt::Display for Error {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 match *self {
44 Error::InvalidDeclaration(ref cause, pos) => {
45 write!(f, "invalid XML declaration at {} cause {}", pos, cause)
46 }
47 Error::InvalidConditionalComment(ref cause, pos) => {
48 write!(f, "invalid conditional comment at {} cause {}", pos, cause)
49 }
50 Error::InvalidComment(ref cause, pos) => {
51 write!(f, "invalid comment at {} cause {}", pos, cause)
52 }
53 Error::InvalidPI(ref cause, pos) => {
54 write!(
55 f,
56 "invalid processing instruction at {} cause {}",
57 pos, cause
58 )
59 }
60 Error::InvalidDoctype(ref cause, pos) => {
61 write!(f, "invalid DTD at {} cause {}", pos, cause)
62 }
63 Error::InvalidEntity(ref cause, pos) => {
64 write!(f, "invalid DTD entity at {} cause {}", pos, cause)
65 }
66 Error::InvalidElement(ref cause, pos) => {
67 write!(f, "invalid element at {} cause {}", pos, cause)
68 }
69 Error::InvalidAttribute(ref cause, pos) => {
70 write!(f, "invalid attribute at {} cause {}", pos, cause)
71 }
72 Error::InvalidCdata(ref cause, pos) => {
73 write!(f, "invalid CDATA at {} cause {}", pos, cause)
74 }
75 Error::InvalidCharData(ref cause, pos) => {
76 write!(f, "invalid character data at {} cause {}", pos, cause)
77 }
78 Error::UnknownToken(pos) => {
79 write!(f, "unknown token at {}", pos)
80 }
81 }
82 }
83}
84
85#[cfg(feature = "std")]
86impl error::Error for Error {
87 fn description(&self) -> &str {
88 "an XML parsing error"
89 }
90}
91
92#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
94pub enum StreamError {
95 UnexpectedEndOfStream,
100
101 InvalidName,
103
104 NonXmlChar(char, TextPos),
108
109 InvalidChar(u8, u8, TextPos),
115
116 InvalidCharMultiple(u8, &'static [u8], TextPos),
120
121 InvalidQuote(u8, TextPos),
123
124 InvalidSpace(u8, TextPos),
128
129 InvalidString(&'static str, TextPos),
133
134 InvalidReference,
136
137 InvalidExternalID,
139
140 InvalidCommentData,
142
143 InvalidCommentEnd,
145
146 InvalidCharacterData,
150}
151
152impl fmt::Display for StreamError {
153 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154 match *self {
155 StreamError::UnexpectedEndOfStream => {
156 write!(f, "unexpected end of stream")
157 }
158 StreamError::InvalidName => {
159 write!(f, "invalid name token")
160 }
161 StreamError::NonXmlChar(c, pos) => {
162 write!(f, "a non-XML character {:?} found at {}", c, pos)
163 }
164 StreamError::InvalidChar(actual, expected, pos) => {
165 write!(
166 f,
167 "expected '{}' not '{}' at {}",
168 expected as char, actual as char, pos
169 )
170 }
171 StreamError::InvalidCharMultiple(actual, expected, pos) => {
172 let mut expected_iter = expected.iter().peekable();
173
174 write!(f, "expected ")?;
175 while let Some(&c) = expected_iter.next() {
176 write!(f, "'{}'", c as char)?;
177 if expected_iter.peek().is_some() {
178 write!(f, ", ")?;
179 }
180 }
181 write!(f, " not '{}' at {}", actual as char, pos)
182 }
183 StreamError::InvalidQuote(c, pos) => {
184 write!(f, "expected quote mark not '{}' at {}", c as char, pos)
185 }
186 StreamError::InvalidSpace(c, pos) => {
187 write!(f, "expected space not '{}' at {}", c as char, pos)
188 }
189 StreamError::InvalidString(expected, pos) => {
190 write!(f, "expected '{}' at {}", expected, pos)
191 }
192 StreamError::InvalidReference => {
193 write!(f, "invalid reference")
194 }
195 StreamError::InvalidExternalID => {
196 write!(f, "invalid ExternalID")
197 }
198 StreamError::InvalidCommentData => {
199 write!(f, "'--' is not allowed in comments")
200 }
201 StreamError::InvalidCommentEnd => {
202 write!(f, "comment cannot end with '-'")
203 }
204 StreamError::InvalidCharacterData => {
205 write!(f, "']]>' is not allowed inside a character data")
206 }
207 }
208 }
209}
210
211#[cfg(feature = "std")]
212impl error::Error for StreamError {
213 fn description(&self) -> &str {
214 "an XML stream parsing error"
215 }
216}
217
218#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
222#[allow(missing_docs)]
223pub struct TextPos {
224 pub row: u32,
225 pub col: u32,
226}
227
228impl TextPos {
229 pub fn new(row: u32, col: u32) -> TextPos {
233 TextPos { row, col }
234 }
235}
236
237impl fmt::Display for TextPos {
238 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239 write!(f, "{}:{}", self.row, self.col)
240 }
241}