simplifies parse loop, allows leading '+', parametrizes Error on T::Err

This commit is contained in:
Alan Liddell 2017-07-19 06:03:05 -04:00
parent add0fbf0f0
commit 16a180f132
1 changed files with 49 additions and 53 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 + std::fmt::Debug, T::Err: Error + PartialEq T: FromStr + Num + PartialOrd + Clone, T::Err: Error
{ {
type Err = ParseComplexError<T>; type Err = ParseComplexError<T::Err>;
/// 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<T>> fn from_str(s: &str) -> Result<Complex<T>, ParseComplexError<T::Err>>
{ {
let imag = match s.rfind('j') { let imag = match s.rfind('j') {
None => 'i', None => 'i',
@ -758,46 +758,38 @@ impl<T> FromStr for Complex<T> where
let mut b = String::with_capacity(s.len()); let mut b = String::with_capacity(s.len());
let mut first = true; let mut first = true;
let mut char_indices = s.char_indices(); let char_indices = s.char_indices();
let mut pc = ' '; let mut pc = ' ';
let mut split_index = s.len(); let mut split_index = s.len();
loop { for (i, cc) in char_indices {
match char_indices.next() { if cc == '+' && pc != 'e' && pc != 'E' && i > 0 {
Some(t) => { // ignore '+' if part of an exponent
let i = t.0; if first {
let cc = t.1; split_index = i;
first = false;
if cc == '+' && pc != 'e' && pc != 'E' { }
// ignore '+' if part of an exponent // don't carry '+' over into b
if first { pc = ' ';
split_index = i; continue;
first = false; } else if cc == '-' && pc != 'e' && pc != 'E' && i > 0 {
} // ignore '-' if part of an exponent or begins the string
// don't carry '+' over into b if first {
pc = ' '; split_index = i;
continue; first = false;
} else if cc == '-' && pc != 'e' && pc != 'E' && i > 0 { }
// ignore '-' if part of an exponent or begins the string // DO carry '-' over into b
if first {
split_index = i;
first = false;
}
// DO carry '-' over into b
}
if pc == '-' && cc == ' ' && !first {
// ignore whitespace between minus sign and next number
continue;
}
if !first {
b.push(cc);
}
pc = cc;
},
None => break,
} }
if pc == '-' && cc == ' ' && !first {
// ignore whitespace between minus sign and next number
continue;
}
if !first {
b.push(cc);
}
pc = cc;
} }
// split off real and imaginary parts, trim whitespace // split off real and imaginary parts, trim whitespace
@ -833,6 +825,8 @@ impl<T> FromStr for Complex<T> where
im = "1"; im = "1";
} else if im == "-" { } else if im == "-" {
im = "-1"; im = "-1";
} else if im == "+" {
im = "1";
} }
// parse im // parse im
@ -867,38 +861,38 @@ impl<T> serde::Deserialize for Complex<T> where
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ParseComplexError<T> where pub struct ParseComplexError<E> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq E: Error
{ {
kind: ComplexErrorKind<T>, kind: ComplexErrorKind<E>,
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
enum ComplexErrorKind<T> where enum ComplexErrorKind<E> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq E: Error
{ {
ParseError(T::Err), ParseError(E),
ExprError ExprError
} }
impl<T> Error for ParseComplexError<T> where impl<E> Error for ParseComplexError<E> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq E: Error
{ {
fn description(&self) -> &str { fn description(&self) -> &str {
self.kind.description() self.kind.description()
} }
} }
impl<T> fmt::Display for ParseComplexError<T> where impl<E> fmt::Display for ParseComplexError<E> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq E: Error
{ {
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<T> ComplexErrorKind<T> where impl<E> ComplexErrorKind<E> where
T: FromStr + std::fmt::Debug + PartialEq, T::Err: Error + PartialEq E: Error
{ {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
@ -1560,12 +1554,13 @@ mod test {
test(_0_0i, "-0"); test(_0_0i, "-0");
test(_0_0i, "0i"); test(_0_0i, "0i");
test(_0_0i, "0j"); test(_0_0i, "0j");
test(_0_0i, "+0j");
test(_0_0i, "-0i"); test(_0_0i, "-0i");
test(_1_0i, "1 + 0i"); test(_1_0i, "1 + 0i");
test(_1_0i, "1+0j"); test(_1_0i, "1+0j");
test(_1_0i, "1 - 0j"); test(_1_0i, "1 - 0j");
test(_1_0i, "1-0i"); test(_1_0i, "+1-0i");
test(_1_0i, "-0j+1"); test(_1_0i, "-0j+1");
test(_1_0i, "1"); test(_1_0i, "1");
@ -1575,7 +1570,7 @@ mod test {
test(_1_1i, "1+1i"); test(_1_1i, "1+1i");
test(_1_1i, "i + 1"); test(_1_1i, "i + 1");
test(_1_1i, "1i+1"); test(_1_1i, "1i+1");
test(_1_1i, "j+1"); test(_1_1i, "+j+1");
test(_0_1i, "0 + i"); test(_0_1i, "0 + i");
test(_0_1i, "0+j"); test(_0_1i, "0+j");
@ -1618,5 +1613,6 @@ mod test {
test("314e-2ij"); test("314e-2ij");
test("4.3j - i"); test("4.3j - i");
test("1i - 2i"); test("1i - 2i");
test("+ 1 - 3.0i");
} }
} }