]> git.lizzy.rs Git - rust.git/commitdiff
core: Shuffle around float parsing
authorAlex Crichton <alex@alexcrichton.com>
Mon, 17 Aug 2015 21:16:41 +0000 (14:16 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 18 Aug 2015 02:35:52 +0000 (19:35 -0700)
Stop using stability to hide the implementation details of ParseFloatError and
instead move the error type into the `dec2flt` module. Also move the
implementation blocks of `FromStr for f{32,64}` into `dec2flt` directly.

src/libcore/num/dec2flt/mod.rs
src/libcore/num/float_macros.rs
src/libcore/num/mod.rs
src/libcoretest/atomic.rs
src/libcoretest/num/dec2flt/mod.rs
src/libcoretest/num/uint_macros.rs
src/test/compile-fail/issue-1920-1.rs
src/test/compile-fail/issue-1920-2.rs
src/test/compile-fail/issue-1920-3.rs

index 7c3c384ea93b7f5285fd8380b3a7e076454ece43..4e6b6f04e9e9225a522a96bb705ad5d3f23f3eeb 100644 (file)
@@ -96,8 +96,9 @@
             issue = "0")]
 
 use prelude::v1::*;
-use num::ParseFloatError as PFE;
-use num::FloatErrorKind;
+use fmt;
+use str::FromStr;
+
 use self::parse::{parse_decimal, Decimal, Sign};
 use self::parse::ParseResult::{self, Valid, ShortcutToInf, ShortcutToZero};
 use self::num::digits_to_big;
 pub mod rawfp;
 pub mod parse;
 
-/// Entry point for decimal-to-f32 conversion.
-pub fn to_f32(s: &str) -> Result<f32, PFE> {
-    dec2flt(s)
+macro_rules! from_str_float_impl {
+    ($t:ty, $func:ident) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl FromStr for $t {
+            type Err = ParseFloatError;
+
+            /// Converts a string in base 10 to a float.
+            /// Accepts an optional decimal exponent.
+            ///
+            /// This function accepts strings such as
+            ///
+            /// * '3.14'
+            /// * '-3.14'
+            /// * '2.5E10', or equivalently, '2.5e10'
+            /// * '2.5E-10'
+            /// * '.' (understood as 0)
+            /// * '5.'
+            /// * '.5', or, equivalently,  '0.5'
+            /// * 'inf', '-inf', 'NaN'
+            ///
+            /// Leading and trailing whitespace represent an error.
+            ///
+            /// # Arguments
+            ///
+            /// * src - A string
+            ///
+            /// # Return value
+            ///
+            /// `Err(ParseFloatError)` if the string did not represent a valid
+            /// number.  Otherwise, `Ok(n)` where `n` is the floating-point
+            /// number represented by `src`.
+            #[inline]
+            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
+                dec2flt(src)
+            }
+        }
+    }
+}
+from_str_float_impl!(f32, to_f32);
+from_str_float_impl!(f64, to_f64);
+
+/// An error which can be returned when parsing a float.
+#[derive(Debug, Clone, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ParseFloatError {
+    kind: FloatErrorKind
+}
+
+#[derive(Debug, Clone, PartialEq)]
+enum FloatErrorKind {
+    Empty,
+    Invalid,
+}
+
+impl ParseFloatError {
+    #[unstable(feature = "int_error_internals",
+               reason = "available through Error trait and this method should \
+                         not be exposed publicly",
+               issue = "0")]
+    #[doc(hidden)]
+    pub fn __description(&self) -> &str {
+        match self.kind {
+            FloatErrorKind::Empty => "cannot parse float from empty string",
+            FloatErrorKind::Invalid => "invalid float literal",
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for ParseFloatError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.__description().fmt(f)
+    }
+}
+
+pub fn pfe_empty() -> ParseFloatError {
+    ParseFloatError { kind: FloatErrorKind::Empty }
 }
 
-/// Entry point for decimal-to-f64 conversion.
-pub fn to_f64(s: &str) -> Result<f64, PFE> {
-    dec2flt(s)
+pub fn pfe_invalid() -> ParseFloatError {
+    ParseFloatError { kind: FloatErrorKind::Invalid }
 }
 
 /// Split decimal string into sign and the rest, without inspecting or validating the rest.
@@ -131,9 +205,9 @@ fn extract_sign(s: &str) -> (Sign, &str) {
 }
 
 /// Convert a decimal string into a floating point number.
-fn dec2flt<T: RawFloat>(s: &str) -> Result<T, PFE> {
+fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
     if s.is_empty() {
-        return Err(PFE { __kind: FloatErrorKind::Empty });
+        return Err(pfe_empty())
     }
     let (sign, s) = extract_sign(s);
     let flt = match parse_decimal(s) {
@@ -143,7 +217,7 @@ fn dec2flt<T: RawFloat>(s: &str) -> Result<T, PFE> {
         ParseResult::Invalid => match s {
             "inf" => T::infinity(),
             "NaN" => T::nan(),
-            _ => { return Err(PFE { __kind: FloatErrorKind::Invalid }); }
+            _ => { return Err(pfe_invalid()); }
         }
     };
 
@@ -155,7 +229,7 @@ fn dec2flt<T: RawFloat>(s: &str) -> Result<T, PFE> {
 
 /// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
 /// and figure out which algorithm should do the actual conversion.
-fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, PFE> {
+fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, ParseFloatError> {
     simplify(&mut decimal);
     if let Some(x) = trivial_cases(&decimal) {
         return Ok(x);
@@ -172,7 +246,7 @@ fn convert<T: RawFloat>(mut decimal: Decimal) -> Result<T, PFE> {
     // If we exceed this, perhaps while calculating `f * 10^e` in Algorithm R or Algorithm M,
     // we'll crash. So we error out before getting too close, with a generous safety margin.
     if max_digits > 375 {
-        return Err(PFE { __kind: FloatErrorKind::Invalid });
+        return Err(pfe_invalid());
     }
     let f = digits_to_big(decimal.integral, decimal.fractional);
 
index e3fa7047ec88c71be6253723e6509d2e48c9376a..88c3b756793a2b9bb9dd4664024f69c4f4a01ea7 100644 (file)
@@ -23,8 +23,7 @@ macro_rules! from_str_radix_float_impl {
     ($T:ty) => {
         fn from_str_radix(src: &str, radix: u32)
                           -> Result<$T, ParseFloatError> {
-            use num::FloatErrorKind::*;
-            use num::ParseFloatError as PFE;
+            use num::dec2flt::{pfe_empty, pfe_invalid};
 
             // Special values
             match src {
@@ -35,8 +34,8 @@ fn from_str_radix(src: &str, radix: u32)
             }
 
             let (is_positive, src) =  match src.slice_shift_char() {
-                None             => return Err(PFE { __kind: Empty }),
-                Some(('-', ""))  => return Err(PFE { __kind: Empty }),
+                None             => return Err(pfe_empty()),
+                Some(('-', ""))  => return Err(pfe_empty()),
                 Some(('-', src)) => (false, src),
                 Some((_, _))     => (true,  src),
             };
@@ -88,7 +87,7 @@ fn from_str_radix(src: &str, radix: u32)
                             break;  // start of fractional part
                         },
                         _ => {
-                            return Err(PFE { __kind: Invalid });
+                            return Err(pfe_invalid())
                         },
                     },
                 }
@@ -122,7 +121,7 @@ fn from_str_radix(src: &str, radix: u32)
                                 break; // start of exponent
                             },
                             _ => {
-                                return Err(PFE { __kind: Invalid });
+                                return Err(pfe_invalid())
                             },
                         },
                     }
@@ -135,7 +134,7 @@ fn from_str_radix(src: &str, radix: u32)
                     let base = match c {
                         'E' | 'e' if radix == 10 => 10.0,
                         'P' | 'p' if radix == 16 => 2.0,
-                        _ => return Err(PFE { __kind: Invalid }),
+                        _ => return Err(pfe_invalid()),
                     };
 
                     // Parse the exponent as decimal integer
@@ -144,13 +143,13 @@ fn from_str_radix(src: &str, radix: u32)
                         Some(('-', src)) => (false, src.parse::<usize>()),
                         Some(('+', src)) => (true,  src.parse::<usize>()),
                         Some((_, _))     => (true,  src.parse::<usize>()),
-                        None             => return Err(PFE { __kind: Invalid }),
+                        None             => return Err(pfe_invalid()),
                     };
 
                     match (is_positive, exp) {
                         (true,  Ok(exp)) => base.powi(exp as i32),
                         (false, Ok(exp)) => 1.0 / base.powi(exp as i32),
-                        (_, Err(_))      => return Err(PFE { __kind: Invalid }),
+                        (_, Err(_))      => return Err(pfe_invalid()),
                     }
                 },
                 None => 1.0, // no exponent
index 086437445dec7e85d779970cd19b1475d3f3f61a..8770f46bc8ec9569b1ad0d8885ee1b278f9d1eca 100644 (file)
@@ -1365,47 +1365,6 @@ pub trait Float: Sized {
     fn to_radians(self) -> Self;
 }
 
-macro_rules! from_str_float_impl {
-    ($t:ty, $func:ident) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl FromStr for $t {
-            type Err = ParseFloatError;
-
-            /// Converts a string in base 10 to a float.
-            /// Accepts an optional decimal exponent.
-            ///
-            /// This function accepts strings such as
-            ///
-            /// * '3.14'
-            /// * '-3.14'
-            /// * '2.5E10', or equivalently, '2.5e10'
-            /// * '2.5E-10'
-            /// * '.' (understood as 0)
-            /// * '5.'
-            /// * '.5', or, equivalently,  '0.5'
-            /// * 'inf', '-inf', 'NaN'
-            ///
-            /// Leading and trailing whitespace represent an error.
-            ///
-            /// # Arguments
-            ///
-            /// * src - A string
-            ///
-            /// # Return value
-            ///
-            /// `Err(ParseFloatError)` if the string did not represent a valid
-            /// number.  Otherwise, `Ok(n)` where `n` is the floating-point
-            /// number represented by `src`.
-            #[inline]
-            fn from_str(src: &str) -> Result<Self, ParseFloatError> {
-                dec2flt::$func(src)
-            }
-        }
-    }
-}
-from_str_float_impl!(f32, to_f32);
-from_str_float_impl!(f64, to_f64);
-
 macro_rules! from_str_radix_int_impl {
     ($($t:ty)*) => {$(
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -1548,40 +1507,4 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-/// An error which can be returned when parsing a float.
-#[derive(Debug, Clone, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseFloatError {
-    #[doc(hidden)]
-    #[unstable(feature = "float_error_internals",
-               reason = "should not be exposed publicly",
-               issue = "0")]
-    pub __kind: FloatErrorKind
-}
-
-#[derive(Debug, Clone, PartialEq)]
-#[unstable(feature = "float_error_internals",
-           reason = "should not be exposed publicly",
-           issue = "0")]
-#[doc(hidden)]
-pub enum FloatErrorKind {
-    Empty,
-    Invalid,
-}
-
-impl ParseFloatError {
-    #[doc(hidden)]
-    pub fn __description(&self) -> &str {
-        match self.__kind {
-            FloatErrorKind::Empty => "cannot parse float from empty string",
-            FloatErrorKind::Invalid => "invalid float literal",
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for ParseFloatError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.__description().fmt(f)
-    }
-}
+pub use num::dec2flt::ParseFloatError;
index c50f18c235233ff57dfd2e5b897c657b7dbd7412..b6bb5fddf4a4bdc4fed02347bfc312cc53636f0e 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::atomic::*;
-use core::atomic::Ordering::SeqCst;
+use core::sync::atomic::*;
+use core::sync::atomic::Ordering::SeqCst;
 
 #[test]
 fn bool_() {
index b7ef956055e29738db6b75aa5a4c23b26adcbceb..131cf62957537ea4283ae43383ee2293d7329c12 100644 (file)
@@ -12,7 +12,6 @@
 
 use std::{i64, f32, f64};
 use test;
-use core::num::dec2flt::{to_f32, to_f64};
 
 mod parse;
 mod rawfp;
@@ -27,11 +26,11 @@ macro_rules! test_literal {
         let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
         for input in inputs {
             if input != "inf" {
-                assert_eq!(to_f64(input), Ok(x64));
-                assert_eq!(to_f32(input), Ok(x32));
+                assert_eq!(input.parse(), Ok(x64));
+                assert_eq!(input.parse(), Ok(x32));
                 let neg_input = &format!("-{}", input);
-                assert_eq!(to_f64(neg_input), Ok(-x64));
-                assert_eq!(to_f32(neg_input), Ok(-x32));
+                assert_eq!(neg_input.parse(), Ok(-x64));
+                assert_eq!(neg_input.parse(), Ok(-x32));
             }
         }
     })
@@ -99,83 +98,83 @@ fn fast_path_correct() {
 
 #[test]
 fn lonely_dot() {
-    assert_eq!(to_f64("."), Ok(0.0));
+    assert_eq!(".".parse(), Ok(0.0));
 }
 
 #[test]
 fn nan() {
-    assert!(to_f64("NaN").unwrap().is_nan());
-    assert!(to_f32("NaN").unwrap().is_nan());
+    assert!("NaN".parse::<f32>().unwrap().is_nan());
+    assert!("NaN".parse::<f64>().unwrap().is_nan());
 }
 
 #[test]
 fn inf() {
-    assert_eq!(to_f64("inf"), Ok(f64::INFINITY));
-    assert_eq!(to_f64("-inf"), Ok(f64::NEG_INFINITY));
-    assert_eq!(to_f32("inf"), Ok(f32::INFINITY));
-    assert_eq!(to_f32("-inf"), Ok(f32::NEG_INFINITY));
+    assert_eq!("inf".parse(), Ok(f64::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+    assert_eq!("inf".parse(), Ok(f32::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
 }
 
 #[test]
 fn massive_exponent() {
     let max = i64::MAX;
-    assert_eq!(to_f64(&format!("1e{}000", max)), Ok(f64::INFINITY));
-    assert_eq!(to_f64(&format!("1e-{}000", max)), Ok(0.0));
-    assert_eq!(to_f64(&format!("1e{}000", max)), Ok(f64::INFINITY));
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
+    assert_eq!(format!("1e-{}000", max).parse(), Ok(0.0));
+    assert_eq!(format!("1e{}000", max).parse(), Ok(f64::INFINITY));
 }
 
 #[bench]
 fn bench_0(b: &mut test::Bencher) {
-    b.iter(|| to_f64("0.0"));
+    b.iter(|| "0.0".parse::<f64>());
 }
 
 #[bench]
 fn bench_42(b: &mut test::Bencher) {
-    b.iter(|| to_f64("42"));
+    b.iter(|| "42".parse::<f64>());
 }
 
 #[bench]
 fn bench_huge_int(b: &mut test::Bencher) {
     // 2^128 - 1
-    b.iter(|| to_f64("170141183460469231731687303715884105727"));
+    b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
 }
 
 #[bench]
 fn bench_short_decimal(b: &mut test::Bencher) {
-    b.iter(|| to_f64("1234.5678"));
+    b.iter(|| "1234.5678".parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_long(b: &mut test::Bencher) {
-    b.iter(|| to_f64("3.14159265358979323846264338327950288"));
+    b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
 }
 
 #[bench]
 fn bench_pi_short(b: &mut test::Bencher) {
-    b.iter(|| to_f64("3.141592653589793"))
+    b.iter(|| "3.141592653589793".parse::<f64>())
 }
 
 #[bench]
 fn bench_1e150(b: &mut test::Bencher) {
-    b.iter(|| to_f64("1e150"));
+    b.iter(|| "1e150".parse::<f64>());
 }
 
 #[bench]
 fn bench_long_decimal_and_exp(b: &mut test::Bencher) {
-    b.iter(|| to_f64("727501488517303786137132964064381141071e-123"));
+    b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
 }
 
 #[bench]
 fn bench_min_subnormal(b: &mut test::Bencher) {
-    b.iter(|| to_f64("5e-324"));
+    b.iter(|| "5e-324".parse::<f64>());
 }
 
 #[bench]
 fn bench_min_normal(b: &mut test::Bencher) {
-    b.iter(|| to_f64("2.2250738585072014e-308"));
+    b.iter(|| "2.2250738585072014e-308".parse::<f64>());
 }
 
 #[bench]
 fn bench_max(b: &mut test::Bencher) {
-    b.iter(|| to_f64("1.7976931348623157e308"));
+    b.iter(|| "1.7976931348623157e308".parse::<f64>());
 }
index 6238c6d43e353e033b3ee54314518e9fe38ee5ab..25591db64d9070bbc3c781a8a0d3d3a4b5bed9b2 100644 (file)
@@ -14,7 +14,7 @@ mod tests {
     use core::$T_i::*;
     use num;
     use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
-    use std::str;
+    use std::str::FromStr;
 
     #[test]
     fn test_overflows() {
@@ -152,5 +152,5 @@ pub fn test_parse_bytes() {
         assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
         assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
     }
-
+}
 )}
index c26c5ff8421d960225202b71239249c9be20984d..8c75d4680faebd7fbeef1258fd5a38442053b2e9 100644 (file)
@@ -17,6 +17,6 @@ mod foo {
 fn assert_clone<T>() where T : Clone { }
 
 fn main() {
-    assert_clone::<foo::core::atomic::AtomicBool>();
+    assert_clone::<foo::core::sync::atomic::AtomicBool>();
     //~^ ERROR the trait `foo::core::clone::Clone` is not implemented for the type `foo::core::
-}
\ No newline at end of file
+}
index 63cfcbdd8c700ac5a4b42191a93e316112f581db..57eb82a156bbfaf55c6328c74f94cef5ce0d9870 100644 (file)
@@ -15,6 +15,6 @@
 fn assert_clone<T>() where T : Clone { }
 
 fn main() {
-    assert_clone::<bar::atomic::AtomicBool>();
-    //~^ ERROR the trait `bar::clone::Clone` is not implemented for the type `bar::atomic::
-}
\ No newline at end of file
+    assert_clone::<bar::sync::atomic::AtomicBool>();
+    //~^ ERROR the trait `bar::clone::Clone` is not implemented for the type `bar::sync::atomic::
+}
index 619c8c3f3a4f01d3b0e60ebd0650a48c67f407c5..0ef7747c8a84f124c4310cd9b4fe825c29053a0d 100644 (file)
@@ -19,6 +19,6 @@ mod foo {
 fn assert_clone<T>() where T : Clone { }
 
 fn main() {
-    assert_clone::<foo::core::atomic::AtomicBool>();
-    //~^ ERROR the trait `core::clone::Clone` is not implemented for the type `core::atomic::
-}
\ No newline at end of file
+    assert_clone::<foo::core::sync::atomic::AtomicBool>();
+    //~^ ERROR the trait `core::clone::Clone` is not implemented for the type `core::sync::atomic::
+}