More informative error messages for complex::from_str

This commit is contained in:
Alan Liddell 2017-07-16 15:20:50 -04:00
parent 38ee1304bb
commit add0fbf0f0
1 changed files with 29 additions and 17 deletions

View File

@ -743,12 +743,12 @@ impl<T> fmt::Binary for Complex<T> where
} }
impl<T> FromStr for Complex<T> where impl<T> FromStr for Complex<T> where
T: FromStr + Num + PartialOrd + Clone T: FromStr + Num + PartialOrd + Clone + std::fmt::Debug, T::Err: Error + PartialEq
{ {
type Err = ParseComplexError; type Err = ParseComplexError<T>;
/// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T` /// Parses `a +/- bi`; `ai +/- b`; `a`; or `bi` where `a` and `b` are of type `T`
fn from_str(s: &str) -> Result<Complex<T>, ParseComplexError> fn from_str(s: &str) -> Result<Complex<T>, ParseComplexError<T>>
{ {
let imag = match s.rfind('j') { let imag = match s.rfind('j') {
None => 'i', None => 'i',
@ -819,12 +819,12 @@ impl<T> FromStr for Complex<T> where
} else if b.ends_with(imag) { } else if b.ends_with(imag) {
re = a; im = b; re = a; im = b;
} else { } else {
return Err(ParseComplexError { kind: ComplexErrorKind::ParseError }); return Err(ParseComplexError { kind: ComplexErrorKind::ExprError });
} }
// parse re // parse re
let re = try!(T::from_str(re) let re = try!(T::from_str(re)
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })); .map_err(|e| ParseComplexError { kind: ComplexErrorKind::ParseError(e) }));
// pop imaginary unit off // pop imaginary unit off
let mut im = &im[..im.len()-1]; let mut im = &im[..im.len()-1];
@ -837,7 +837,7 @@ impl<T> FromStr for Complex<T> where
// parse im // parse im
let im = try!(T::from_str(im) let im = try!(T::from_str(im)
.map_err(|_| ParseComplexError { kind: ComplexErrorKind::ParseError })); .map_err(|e| ParseComplexError { kind: ComplexErrorKind::ParseError(e) }));
Ok(Complex::new(re, im)) Ok(Complex::new(re, im))
} }
@ -866,32 +866,44 @@ impl<T> serde::Deserialize for Complex<T> where
} }
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ParseComplexError { pub struct ParseComplexError<T> where
kind: ComplexErrorKind, T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq
{
kind: ComplexErrorKind<T>,
} }
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum ComplexErrorKind { enum ComplexErrorKind<T> where
ParseError, T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq
{
ParseError(T::Err),
ExprError
} }
impl Error for ParseComplexError { impl<T> Error for ParseComplexError<T> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq
{
fn description(&self) -> &str { fn description(&self) -> &str {
self.kind.description() self.kind.description()
} }
} }
impl fmt::Display for ParseComplexError { impl<T> fmt::Display for ParseComplexError<T> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f) self.description().fmt(f)
} }
} }
impl ComplexErrorKind { impl<T> ComplexErrorKind<T> where
fn description(&self) -> &'static str { T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq
{
fn description(&self) -> &str {
match *self { match *self {
ComplexErrorKind::ParseError => "failed to parse complex number", ComplexErrorKind::ParseError(ref e) => e.description(),
ComplexErrorKind::ExprError => "invalid or unsupported complex expression"
} }
} }
} }