From 8eff38b6f6b0a0c76794812df6a5077bfa8e6e19 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 1 Aug 2015 13:40:28 -0700 Subject: [PATCH] Eliminate some code duplication parsing an exponent as an integer --- serde_json/src/de.rs | 49 ++++++++++++++++++---------------- serde_tests/tests/test_json.rs | 14 +++++++--- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/serde_json/src/de.rs b/serde_json/src/de.rs index 4328fec5..4d2ab5c3 100644 --- a/serde_json/src/de.rs +++ b/serde_json/src/de.rs @@ -222,17 +222,20 @@ impl Deserializer Ok(accum) } - fn parse_decimal(&mut self, res: f64) -> Result { + fn parse_decimal(&mut self, mut res: f64) -> Result { try!(self.bump()); + let mut dec = 0.1; + // Make sure a digit follows the decimal place. match self.ch_or_null() { - b'0' ... b'9' => (), + c @ b'0' ... b'9' => { + try!(self.bump()); + res += (((c as u64) - (b'0' as u64)) as f64) * dec; + } _ => { return Err(self.error(ErrorCode::InvalidNumber)); } } - let mut res = res; - let mut dec = 1.0; while !self.eof() { match self.ch_or_null() { c @ b'0' ... b'9' => { @@ -250,30 +253,30 @@ impl Deserializer fn parse_exponent(&mut self, mut res: f64) -> Result { try!(self.bump()); - let mut exp: u64 = 0; - let mut neg_exp = false; - - if self.ch_is(b'+') { - try!(self.bump()); - } else if self.ch_is(b'-') { - try!(self.bump()); - neg_exp = true; - } + let pos = match self.ch_or_null() { + b'+' => { try!(self.bump()); true } + b'-' => { try!(self.bump()); false } + _ => { true } + }; // Make sure a digit follows the exponent place. - match self.ch_or_null() { - b'0' ... b'9' => (), + let mut exp = match self.ch_or_null() { + c @ b'0' ... b'9' => { + try!(self.bump()); + (c as u64) - (b'0' as u64) + } _ => { return Err(self.error(ErrorCode::InvalidNumber)); } - } - while !self.eof() { + }; + + loop { match self.ch_or_null() { c @ b'0' ... b'9' => { + try!(self.bump()); + exp = try_or_invalid!(self, exp.checked_mul(10)); exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64))); - - try!(self.bump()); } - _ => break + _ => { break; } } } @@ -283,10 +286,10 @@ impl Deserializer return Err(self.error(ErrorCode::InvalidNumber)); }; - if neg_exp { - res /= exp; - } else { + if pos { res *= exp; + } else { + res /= exp; } Ok(res) diff --git a/serde_tests/tests/test_json.rs b/serde_tests/tests/test_json.rs index 10bc2f4c..3b6bfb61 100644 --- a/serde_tests/tests/test_json.rs +++ b/serde_tests/tests/test_json.rs @@ -708,7 +708,7 @@ fn test_parse_number_errors() { ("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)), ("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)), ("777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 20)), - ("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 22)), + ("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 23)), ]); } @@ -735,13 +735,21 @@ fn test_parse_f64() { test_parse_ok(vec![ ("0.0", 0.0f64), ("3.0", 3.0f64), + ("3.00", 3.0f64), ("3.1", 3.1), ("-1.2", -1.2), ("0.4", 0.4), ("0.4e5", 0.4e5), + ("0.4e+5", 0.4e5), ("0.4e15", 0.4e15), - ("0.4e-01", 0.4e-01), - (" 0.4e-01 ", 0.4e-01), + ("0.4e+15", 0.4e15), + ("0.4e-01", 0.4e-1), + (" 0.4e-01 ", 0.4e-1), + ("0.4e-001", 0.4e-1), + ("0.4e-0", 0.4e0), + ("0.00e00", 0.0), + ("0.00e+00", 0.0), + ("0.00e-00", 0.0), ]); }