use std::error::Error;
use std::fmt;
use std::io;
use std::num::{ParseFloatError, ParseIntError};
#[derive(Debug)]
pub struct ScanError {
pub at: ScanErrorAt,
pub kind: ScanErrorKind,
_priv: (),
}
impl ScanError {
pub fn new(at: usize, kind: ScanErrorKind) -> Self {
ScanError {
at: ScanErrorAt { bytes: at },
kind: kind,
_priv: (),
}
}
pub fn expected_end() -> Self {
Self::new(0, ScanErrorKind::ExpectedEnd)
}
pub fn float(err: ParseFloatError) -> Self {
Self::new(0, ScanErrorKind::Float(err))
}
pub fn int(err: ParseIntError) -> Self {
Self::new(0, ScanErrorKind::Int(err))
}
pub fn io(err: io::Error) -> Self {
Self::new(0, ScanErrorKind::Io(err))
}
pub fn literal_mismatch() -> Self {
Self::new(0, ScanErrorKind::LiteralMismatch)
}
pub fn syntax(desc: &'static str) -> Self {
Self::new(0, ScanErrorKind::Syntax(desc))
}
pub fn syntax_no_message() -> Self {
Self::new(0, ScanErrorKind::SyntaxNoMessage)
}
pub fn other<E: Into<Box<Error>>>(err: E) -> Self {
Self::new(0, ScanErrorKind::from_other(err))
}
pub fn furthest_along(self, other: Self) -> Self {
if self.at.offset() >= other.at.offset() {
self
} else {
other
}
}
pub fn add_offset(self, bytes: usize) -> Self {
ScanError::new(self.at.offset() + bytes, self.kind)
}
}
impl<'a> fmt::Display for ScanError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
try!("scan error: ".fmt(fmt));
try!(self.kind.fmt(fmt));
try!(", at offset: ".fmt(fmt));
try!(self.at.offset().fmt(fmt));
Ok(())
}
}
impl Error for ScanError {
fn cause(&self) -> Option<&Error> {
self.kind.cause()
}
fn description(&self) -> &str {
self.kind.description()
}
}
#[derive(Debug)]
pub struct ScanErrorAt {
bytes: usize,
}
impl ScanErrorAt {
pub fn offset(&self) -> usize {
self.bytes
}
}
#[derive(Debug)]
pub enum ScanErrorKind {
LiteralMismatch,
Syntax(&'static str),
SyntaxNoMessage,
ExpectedEnd,
Float(ParseFloatError),
Int(ParseIntError),
Io(io::Error),
Other(Box<Error>),
#[doc(hidden)]
__DoNotMatch,
}
impl ScanErrorKind {
pub fn from_other<E: Into<Box<Error>>>(err: E) -> Self {
ScanErrorKind::Other(err.into())
}
}
impl fmt::Display for ScanErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use self::ScanErrorKind::*;
match *self {
LiteralMismatch => "did not match literal".fmt(fmt),
Syntax(desc) => {
try!("syntax error: ".fmt(fmt));
try!(desc.fmt(fmt));
Ok(())
},
SyntaxNoMessage => "unknown syntax error".fmt(fmt),
ExpectedEnd => "expected end of input".fmt(fmt),
Float(ref err) => err.fmt(fmt),
Int(ref err) => err.fmt(fmt),
Io(ref err) => err.fmt(fmt),
Other(ref err) => err.fmt(fmt),
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
}
}
}
impl Error for ScanErrorKind {
fn cause(&self) -> Option<&Error> {
use self::ScanErrorKind::*;
match *self {
LiteralMismatch
| Syntax(_)
| SyntaxNoMessage
| ExpectedEnd
=> None,
Float(ref err) => err.cause(),
Int(ref err) => err.cause(),
Io(ref err) => err.cause(),
Other(ref err) => err.cause(),
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
}
}
fn description(&self) -> &str {
use self::ScanErrorKind::*;
match *self {
LiteralMismatch => "did not match literal",
Syntax(_) => "syntax error",
SyntaxNoMessage => "unknown syntax error",
ExpectedEnd => "expected end of input",
Float(ref err) => err.description(),
Int(ref err) => err.description(),
Io(ref err) => err.description(),
Other(ref err) => err.description(),
__DoNotMatch => panic!("do not use ScanErrorKind::__DoNotMatch!"),
}
}
}