1extern crate core;
13use self::core::fmt::{self,Display,Formatter};
14#[cfg(feature="std")]
15use std::error::Error;
16
17
18macro_rules! description {($err:ty, $desc:expr) => {
19 #[cfg(not(feature="std"))]
20 impl $err {
21 #[allow(missing_docs)]
22 pub fn description(&self) -> &'static str {
23 ($desc)(self)
24 }
25 }
26 #[cfg(feature="std")]
27 impl Error for $err {
28 fn description(&self) -> &'static str {
29 ($desc)(self)
30 }
31 }
32 impl Display for $err {
33 fn fmt(&self, fmtr: &mut Formatter) -> fmt::Result {
34 write!(fmtr, "{}", self.description())
35 }
36 }
37}}
38
39
40macro_rules! single_cause {(#[$doc1:meta] #[$doc2:meta] $err:ident => $desc:expr) => {
41 #[$doc1]
43 #[$doc2]
44 #[derive(Clone,Copy, Debug, PartialEq,Eq)]
45 pub struct $err;
46 description!{$err, |_| $desc }
47}}
48
49
50single_cause!{
51 InvalidUtf16FirstUnit => "is a trailing surrogate"
54}
55
56single_cause!{
57 EmptyStrError => "is empty"
60}
61
62single_cause!{
63 NonAsciiError => "is not an ASCII character"
66}
67
68single_cause!{
69 NonBMPError => "is not a codepoint in the basic multilingual plane"
72}
73
74
75
76macro_rules! simple {(#[$tydoc:meta] $err:ident {
77 $($(#[$vardoc:meta])* ::$variant:ident => $string:expr),+,
78 } ) => {
79 #[$tydoc]
80 #[derive(Clone,Copy, Debug, PartialEq,Eq)]
81 pub enum $err {
82 $($(#[$vardoc])* $variant),*
83 }
84 description!{$err, |e: &$err| match *e {$($err::$variant=>$string),*} }
85}}
86
87
88simple!{InvalidCodepoint {
90 ::Utf16Reserved => "is reserved for UTF-16 surrogate pairs",
92 ::TooHigh => "is higher than the highest codepoint",
94 }}
95use self::InvalidCodepoint::*;
96impl InvalidCodepoint {
97 pub fn error_range(self) -> (u32,u32) {match self {
99 Utf16Reserved => (0xd8_00, 0xdf_ff),
100 TooHigh => (0x00_10_ff_ff, 0xff_ff_ff_ff),
101 }}
102}
103
104
105simple!{InvalidUtf16Tuple {
107 ::FirstIsTrailingSurrogate => "the first unit is a trailing / low surrogate, which is never valid",
111 ::SuperfluousSecond => "the second unit is superfluous",
113 ::MissingSecond => "the first unit requires a second unit",
115 ::InvalidSecond => "the required second unit is not a trailing / low surrogate",
119 }}
120
121
122simple!{InvalidUtf16Slice {
124 ::EmptySlice => "the slice is empty",
126 ::FirstLowSurrogate => "the first unit is a trailing surrogate",
128 ::MissingSecond => "the first and only unit requires a second one",
130 ::SecondNotLowSurrogate => "the required second unit is not a trailing surrogate",
132 }}
133
134simple!{Utf16PairError {
136 ::UnexpectedTrailingSurrogate => "a trailing surrogate was not preceeded by a leading surrogate",
138 ::UnmatchedLeadingSurrogate => "a leading surrogate was followed by an unit that was not a trailing surrogate",
140 ::Incomplete => "a trailing surrogate was expected when the end was reached",
142 }}
143
144
145simple!{FromStrError {
147 ::MultipleCodepoints => "has more than one codepoint",
149 ::Empty => "is empty",
151 }}
152
153
154simple!{InvalidUtf8FirstByte {
156 ::TooLongSeqence => "is greater than 247 (UTF-8 sequences cannot be longer than four bytes)",
158 ::ContinuationByte => "is a continuation of a previous sequence",
160 }}
161use self::InvalidUtf8FirstByte::*;
162
163
164
165macro_rules! complex {
166($err:ty
167 {$($sub:ty => $to:expr,)*}
168 {$($desc:pat => $string:expr),+,}
169 => $use_cause:expr =>
170 {$($cause:pat => $result:expr),+,} $(#[$causedoc:meta])*
171) => {
172 $(impl From<$sub> for $err {
173 fn from(error: $sub) -> $err {
174 $to(error)
175 }
176 })*
177 #[cfg(not(feature="std"))]
178 impl $err {
179 #[allow(missing_docs)]
180 pub fn description(&self) -> &'static str {
181 match *self{ $($desc => $string,)* }
182 }
183 fn cause(&self) -> Option<&Display> {None}
185 }
186 #[cfg(feature="std")]
187 impl Error for $err {
188 fn description(&self) -> &'static str {
189 match *self{ $($desc => $string,)* }
190 }
191 $(#[$causedoc])*
192 fn cause(&self) -> Option<&Error> {
193 match *self{ $($cause => $result,)* }
194 }
195 }
196 impl Display for $err {
197 fn fmt(&self, fmtr: &mut Formatter) -> fmt::Result {
198 match (self.cause(), $use_cause) {
199 (Some(d),true) => write!(fmtr, "{}: {}", self.description(), d),
200 _ => write!(fmtr, "{}", self.description()),
201 }
202 }
203 }
204}}
205
206
207#[derive(Clone,Copy, Debug, PartialEq,Eq)]
210pub enum InvalidUtf8 {
211 FirstByte(InvalidUtf8FirstByte),
213 NotAContinuationByte(usize),
216 OverLong,
221}
222use self::InvalidUtf8::*;
223complex!{InvalidUtf8 {
224 InvalidUtf8FirstByte => FirstByte,
225 } {
226 FirstByte(TooLongSeqence) => "the first byte is greater than 239 (UTF-8 sequences cannot be longer than four bytes)",
227 FirstByte(ContinuationByte) => "the first byte is a continuation of a previous sequence",
228 OverLong => "the sequence contains too many zeros and could be shorter",
229 NotAContinuationByte(_) => "the sequence is too short",
230 } => false => {
231 FirstByte(ref cause) => Some(cause),
232 _ => None,
233 }}
235
236
237#[derive(Clone,Copy, Debug, PartialEq,Eq)]
239pub enum InvalidUtf8Array {
240 Utf8(InvalidUtf8),
242 Codepoint(InvalidCodepoint),
244}
245complex!{InvalidUtf8Array {
246 InvalidUtf8 => InvalidUtf8Array::Utf8,
247 InvalidCodepoint => InvalidUtf8Array::Codepoint,
248 } {
249 InvalidUtf8Array::Utf8(_) => "the sequence is invalid UTF-8",
250 InvalidUtf8Array::Codepoint(_) => "the encoded codepoint is invalid",
251 } => true => {
252 InvalidUtf8Array::Utf8(ref u) => Some(u),
253 InvalidUtf8Array::Codepoint(ref c) => Some(c),
254 }}
256
257
258#[derive(Clone,Copy, Debug, PartialEq,Eq)]
260pub enum InvalidUtf8Slice {
261 Utf8(InvalidUtf8),
263 Codepoint(InvalidCodepoint),
265 TooShort(usize),
267}
268complex!{InvalidUtf8Slice {
269 InvalidUtf8 => InvalidUtf8Slice::Utf8,
270 InvalidCodepoint => InvalidUtf8Slice::Codepoint,
271 } {
272 InvalidUtf8Slice::Utf8(_) => "the sequence is invalid UTF-8",
273 InvalidUtf8Slice::Codepoint(_) => "the encoded codepoint is invalid",
274 InvalidUtf8Slice::TooShort(1) => "the slice is empty",
275 InvalidUtf8Slice::TooShort(_) => "the slice is shorter than the sequence",
276 } => true => {
277 InvalidUtf8Slice::Utf8(ref u) => Some(u),
278 InvalidUtf8Slice::Codepoint(ref c) => Some(c),
279 InvalidUtf8Slice::TooShort(_) => None,
280 }
281}