Skip to content

Commit 126b253

Browse files
committed
Improved error codes.
Note that, due to rust-lang/rust#26448 some `ScanFromStr` implementations *cannot* return a `Syntax` error without trigger the aforementioned issue. This is what `SyntaxNoMessage` is for, until it gets fixed.
1 parent 783e6a2 commit 126b253

File tree

7 files changed

+269
-148
lines changed

7 files changed

+269
-148
lines changed

src/error.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Defines error types used by the crate.
44
use std::error::Error;
55
use std::fmt;
66
use std::io;
7+
use std::num::{ParseFloatError, ParseIntError};
78
use input::Cursor;
89

910
/**
@@ -63,10 +64,10 @@ impl<'a> ScanError<'a> {
6364
}
6465

6566
/**
66-
Shorthand for constructing a `Missing` error.
67+
Shorthand for constructing a `Syntax` error.
6768
*/
68-
pub fn missing(at: Cursor<'a>) -> Self {
69-
Self::new(at, ScanErrorKind::Missing)
69+
pub fn syntax(at: Cursor<'a>, desc: &'static str) -> Self {
70+
Self::new(at, ScanErrorKind::Syntax(desc))
7071
}
7172

7273
/**
@@ -126,17 +127,34 @@ pub enum ScanErrorKind {
126127
/// Failed to match a literal pattern term.
127128
LiteralMismatch,
128129

129-
/// Scanning a value failed in some vague fashion.
130-
Missing,
130+
/// General syntax error.
131+
Syntax(&'static str),
132+
133+
/**
134+
General syntax error.
135+
136+
Due to [Rust issue #26448](https://github.com/rust-lang/rust/issues/26448), some scanners which want to return a `Syntax` error *cannot*.
137+
*/
138+
SyntaxNoMessage,
131139

132140
/// Expected end-of-input.
133141
ExpectedEnd,
134142

143+
/// Floating point parsing failed.
144+
Float(ParseFloatError),
145+
146+
/// Integer parsing failed.
147+
Int(ParseIntError),
148+
135149
/// An IO error occurred.
136150
Io(io::Error),
137151

138152
/// Some other error occurred.
139153
Other(Box<Error>),
154+
155+
/// Hidden variant to prevent exhaustive matching.
156+
#[doc(hidden)]
157+
__DoNotMatch,
140158
}
141159

142160
impl ScanErrorKind {
@@ -153,10 +171,18 @@ impl fmt::Display for ScanErrorKind {
153171
use self::ScanErrorKind::*;
154172
match *self {
155173
LiteralMismatch => "did not match literal".fmt(fmt),
156-
Missing => "missing scannable input".fmt(fmt),
174+
Syntax(desc) => {
175+
try!("syntax error: ".fmt(fmt));
176+
try!(desc.fmt(fmt));
177+
Ok(())
178+
},
179+
SyntaxNoMessage => "unknown syntax error".fmt(fmt),
157180
ExpectedEnd => "expected end of input".fmt(fmt),
181+
Float(ref err) => err.fmt(fmt),
182+
Int(ref err) => err.fmt(fmt),
158183
Io(ref err) => err.fmt(fmt),
159184
Other(ref err) => err.fmt(fmt),
185+
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
160186
}
161187
}
162188
}
@@ -165,22 +191,31 @@ impl Error for ScanErrorKind {
165191
fn cause(&self) -> Option<&Error> {
166192
use self::ScanErrorKind::*;
167193
match *self {
168-
LiteralMismatch => None,
169-
Missing => None,
170-
ExpectedEnd => None,
194+
LiteralMismatch
195+
| Syntax(_)
196+
| SyntaxNoMessage
197+
| ExpectedEnd
198+
=> None,
199+
Float(ref err) => err.cause(),
200+
Int(ref err) => err.cause(),
171201
Io(ref err) => err.cause(),
172202
Other(ref err) => err.cause(),
203+
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
173204
}
174205
}
175206

176207
fn description(&self) -> &str {
177208
use self::ScanErrorKind::*;
178209
match *self {
179210
LiteralMismatch => "did not match literal",
180-
Missing => "missing scannable input",
211+
Syntax(_) => "syntax error",
212+
SyntaxNoMessage => "unknown syntax error",
181213
ExpectedEnd => "expected end of input",
214+
Float(ref err) => err.description(),
215+
Int(ref err) => err.description(),
182216
Io(ref err) => err.description(),
183217
Other(ref err) => err.description(),
218+
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
184219
}
185220
}
186221
}

0 commit comments

Comments
 (0)