diff --git a/src/de.rs b/src/de.rs index aa4696a..86d786e 100644 --- a/src/de.rs +++ b/src/de.rs @@ -748,9 +748,9 @@ impl<'de, R: Read<'de>> Deserializer { let fraction = &self.scratch[integer_end..]; let f = if self.requested_f32 { - lexical::parse_float::(integer.iter(), fraction.iter(), exponent) as f64 + lexical::parse_float::(integer, fraction, exponent) as f64 } else { - lexical::parse_float::(integer.iter(), fraction.iter(), exponent) + lexical::parse_float::(integer, fraction, exponent) }; self.scratch.clear(); diff --git a/src/lexical/algorithm.rs b/src/lexical/algorithm.rs index 69ac588..902c740 100644 --- a/src/lexical/algorithm.rs +++ b/src/lexical/algorithm.rs @@ -156,9 +156,9 @@ where /// /// Uses the moderate path, if applicable, otherwise, uses the slow path /// as required. -pub(crate) fn fallback_path<'a, F, Iter1, Iter2>( - integer: Iter1, - fraction: Iter2, +pub(crate) fn fallback_path( + integer: &[u8], + fraction: &[u8], mantissa: u64, exponent: i32, mantissa_exponent: i32, @@ -166,8 +166,6 @@ pub(crate) fn fallback_path<'a, F, Iter1, Iter2>( ) -> F where F: Float, - Iter1: Iterator + Clone, - Iter2: Iterator + Clone, { // Moderate path (use an extended 80-bit representation). let (fp, valid) = moderate_path::(mantissa, mantissa_exponent, truncated); diff --git a/src/lexical/bhcomp.rs b/src/lexical/bhcomp.rs index d138f4a..8cd2378 100644 --- a/src/lexical/bhcomp.rs +++ b/src/lexical/bhcomp.rs @@ -17,10 +17,9 @@ use crate::lib::{cmp, mem}; /// Parse the full mantissa into a big integer. /// /// Max digits is the maximum number of digits plus one. -fn parse_mantissa<'a, F, Iter>(mut iter: Iter) -> Bigint +fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> Bigint where F: Float, - Iter: Iterator + Clone, { // Main loop let small_powers = POW10_LIMB; @@ -32,7 +31,7 @@ where let mut result = Bigint::default(); // Iteratively process all the data in the mantissa. - while let Some(&digit) = iter.next() { + for &digit in integer.iter().chain(fraction) { // We've parsed the max digits using small values, add to bignum if counter == step { result.imul_small(small_powers[counter]); @@ -64,8 +63,7 @@ where // representation. We also need to return an index. // Since we already trimmed trailing zeros, we know there has // to be a non-zero digit if there are any left. - let is_consumed = iter.count() == 0; - if !is_consumed { + if i < integer.len() + fraction.len() { result.imul_small(10); result.iadd_small(1); } @@ -108,10 +106,9 @@ fn round_nearest_tie_even(fp: &mut ExtendedFloat, shift: i32, is_truncated: bool // BHCOMP /// Calculate the mantissa for a big integer with a positive exponent. -fn large_atof<'a, F, Iter>(iter: Iter, exponent: i32) -> F +fn large_atof(mantissa: Bigint, exponent: i32) -> F where F: Float, - Iter: Iterator + Clone, { let bits = mem::size_of::() * 8; @@ -119,7 +116,7 @@ where // Now, we can calculate the mantissa and the exponent from this. // The binary exponent is the binary exponent for the mantissa // shifted to the hidden bit. - let mut bigmant = parse_mantissa::(iter); + let mut bigmant = mantissa; bigmant.imul_pow10(exponent.as_u32()); // Get the exact representation of the float from the big integer. @@ -136,13 +133,12 @@ where /// Calculate the mantissa for a big integer with a negative exponent. /// /// This invokes the comparison with `b+h`. -fn small_atof<'a, F, Iter>(iter: Iter, exponent: i32, f: F) -> F +fn small_atof(mantissa: Bigint, exponent: i32, f: F) -> F where F: Float, - Iter: Iterator + Clone, { // Get the significant digits and radix exponent for the real digits. - let mut real_digits = parse_mantissa::(iter); + let mut real_digits = mantissa; let real_exp = exponent; debug_assert!(real_exp < 0); @@ -198,32 +194,29 @@ where /// The digits iterator must not have any trailing zeros (true for /// `FloatState2`). /// sci_exponent and digits.size_hint() must not overflow i32. -pub(crate) fn bhcomp<'a, F, Iter1, Iter2>(b: F, integer: Iter1, fraction: Iter2, exponent: i32) -> F +pub(crate) fn bhcomp(b: F, integer: &[u8], mut fraction: &[u8], exponent: i32) -> F where F: Float, - Iter1: Iterator + Clone, - Iter2: Iterator + Clone, { // Calculate the number of integer digits and use that to determine // where the significant digits start in the fraction. - let integer_digits = integer.clone().count(); - let fraction_digits = fraction.clone().count(); - let digits_start = match integer_digits { - 0 => fraction.clone().take_while(|&x| x == &b'0').count(), - _ => 0, + let integer_digits = integer.len(); + let fraction_digits = fraction.len(); + let digits_start = if integer_digits == 0 { + let start = fraction.iter().take_while(|&x| *x == b'0').count(); + fraction = &fraction[start..]; + start + } else { + 0 }; let sci_exp = scientific_exponent(exponent, integer_digits, digits_start); let count = F::MAX_DIGITS.min(integer_digits + fraction_digits - digits_start); let scaled_exponent = sci_exp + 1 - count.as_i32(); - // We have a finite conversions number of digits for base10. - // We need to then limit the iterator over that number of digits. - // Skip all leading zeros (can occur if fraction is empty). - let iter = integer.chain(fraction).skip(digits_start); - + let mantissa = parse_mantissa::(integer, fraction); if scaled_exponent >= 0 { - large_atof(iter, scaled_exponent) + large_atof(mantissa, scaled_exponent) } else { - small_atof(iter, scaled_exponent, b) + small_atof(mantissa, scaled_exponent, b) } } diff --git a/src/lexical/parse.rs b/src/lexical/parse.rs index e5a8923..0e173c6 100644 --- a/src/lexical/parse.rs +++ b/src/lexical/parse.rs @@ -12,21 +12,19 @@ use super::num::*; /// /// * `integer` - Slice containing the integer digits. /// * `fraction` - Slice containing the fraction digits. -fn parse_mantissa<'a, Iter1, Iter2>(mut integer: Iter1, mut fraction: Iter2) -> (u64, usize) -where - Iter1: Iterator, - Iter2: Iterator, -{ +fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> (u64, usize) { let mut value: u64 = 0; // On overflow, validate that all the remaining characters are valid // digits, if not, return the first invalid digit. Otherwise, // calculate the number of truncated digits. + let mut integer = integer.iter(); while let Some(c) = integer.next() { value = match add_digit(value, to_digit(*c).unwrap()) { Some(v) => v, - None => return (value, 1 + integer.count() + fraction.count()), + None => return (value, 1 + integer.count() + fraction.len()), }; } + let mut fraction = fraction.iter(); while let Some(c) = fraction.next() { value = match add_digit(value, to_digit(*c).unwrap()) { Some(v) => v, @@ -38,24 +36,19 @@ where /// Parse float from extracted float components. /// -/// * `integer` - Cloneable, forward iterator over integer digits. -/// * `fraction` - Cloneable, forward iterator over integer digits. +/// * `integer` - Slice containing the integer digits. +/// * `fraction` - Slice containing the fraction digits. /// * `exponent` - Parsed, 32-bit exponent. /// /// # Preconditions /// 1). The integer should not have leading zeros. /// 2). The fraction should not have trailing zeros. -/// -/// We cannot efficiently remove trailing zeros while only accepting a -/// forward iterator. -pub fn parse_float<'a, F, Iter1, Iter2>(integer: Iter1, fraction: Iter2, exponent: i32) -> F +pub fn parse_float(integer: &[u8], fraction: &[u8], exponent: i32) -> F where F: Float, - Iter1: Iterator + Clone, - Iter2: Iterator + Clone, { // Parse the mantissa and attempt the fast and moderate-path algorithms. - let (mantissa, truncated) = parse_mantissa(integer.clone(), fraction.clone()); + let (mantissa, truncated) = parse_mantissa(integer, fraction); let is_truncated = truncated != 0; // Process the state to a float. @@ -66,11 +59,11 @@ where F::ZERO } else if !is_truncated { // Try the fast path, no mantissa truncation. - let mant_exp = mantissa_exponent(exponent, fraction.clone().count(), 0); - if let Some(float) = fast_path::(mantissa, mant_exp) { + let mant_exp = mantissa_exponent(exponent, fraction.len(), 0); + if let Some(float) = fast_path(mantissa, mant_exp) { float } else { - fallback_path::( + fallback_path( integer, fraction, mantissa, @@ -80,8 +73,8 @@ where ) } } else { - let mant_exp = mantissa_exponent(exponent, fraction.clone().count(), truncated); - fallback_path::( + let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated); + fallback_path( integer, fraction, mantissa, @@ -101,9 +94,9 @@ mod tests { use core::f64; fn check_parse_float(integer: &str, fraction: &str, exponent: i32, expected: F) { - let integer = integer.as_bytes().iter(); - let fraction = fraction.as_bytes().iter(); - assert!(expected == parse_float::(integer, fraction, exponent)); + let integer = integer.as_bytes(); + let fraction = fraction.as_bytes(); + assert!(expected == parse_float(integer, fraction, exponent)); } #[test]