]> git.lizzy.rs Git - rust.git/commitdiff
optimize from_str_radix
authorarthurprs <arthurprs@gmail.com>
Sat, 18 Jul 2015 21:59:38 +0000 (18:59 -0300)
committerarthurprs <arthurprs@gmail.com>
Sun, 19 Jul 2015 12:54:44 +0000 (09:54 -0300)
src/libcore/num/mod.rs
src/libcoretest/num/mod.rs

index 6413cc36d269bca158cdbce5acc25d7f44553252..bfbb2ded0782dbf4e177d35b00cca42e70e581e2 100644 (file)
@@ -24,6 +24,7 @@
 use option::Option::{self, Some, None};
 use result::Result::{self, Ok, Err};
 use str::{FromStr, StrExt};
+use slice::SliceExt;
 
 /// Provides intentionally-wrapped arithmetic on `T`.
 ///
@@ -1448,19 +1449,30 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
                                          -> Result<T, ParseIntError> {
     use self::IntErrorKind::*;
     use self::ParseIntError as PIE;
+
     assert!(radix >= 2 && radix <= 36,
            "from_str_radix_int: must lie in the range `[2, 36]` - found {}",
            radix);
 
+    if src.is_empty() {
+        return Err(PIE { kind: Empty });
+    }
+
     let is_signed_ty = T::from_u32(0) > T::min_value();
 
-    match src.slice_shift_char() {
-        Some(('-', "")) => Err(PIE { kind: Empty }),
-        Some(('-', src)) if is_signed_ty => {
+    // all valid digits are ascii, so we will just iterate over the utf8 bytes
+    // and cast them to chars. .to_digit() will safely return None for anything
+    // other than a valid ascii digit for a the given radix, including the first-byte
+    // of multi-byte sequences
+    let src = src.as_bytes();
+
+    match (src[0], &src[1..])  {
+        (b'-', digits) if digits.is_empty() => Err(PIE { kind: Empty }),
+        (b'-', digits) if is_signed_ty => {
             // The number is negative
             let mut result = T::from_u32(0);
-            for c in src.chars() {
-                let x = match c.to_digit(radix) {
+            for &c in digits {
+                let x = match (c as char).to_digit(radix) {
                     Some(x) => x,
                     None => return Err(PIE { kind: InvalidDigit }),
                 };
@@ -1475,11 +1487,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
             }
             Ok(result)
         },
-        Some((_, _)) => {
+        (c, digits) => {
             // The number is signed
-            let mut result = T::from_u32(0);
-            for c in src.chars() {
-                let x = match c.to_digit(radix) {
+            let mut result = match (c as char).to_digit(radix) {
+                Some(x) => T::from_u32(x),
+                None => return Err(PIE { kind: InvalidDigit }),
+            };
+            for &c in digits {
+                let x = match (c as char).to_digit(radix) {
                     Some(x) => x,
                     None => return Err(PIE { kind: InvalidDigit }),
                 };
@@ -1493,8 +1508,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
                 };
             }
             Ok(result)
-        },
-        None => Err(ParseIntError { kind: Empty }),
+        }
     }
 }
 
index 998f4b21ece7f8f8345ccac81ffcfe8e4fadbba2..a9baa2cc477f6c326923888cb80bfa3bc162eb05 100644 (file)
@@ -117,7 +117,14 @@ fn test_int_from_str_overflow() {
     }
 
     #[test]
-    fn test_int_from_minus_sign() {
-        assert_eq!("-".parse::<i32>().ok(), None);
+    fn test_invalid() {
+        assert_eq!("--129".parse::<i8>().ok(), None);
+        assert_eq!("Съешь".parse::<u8>().ok(), None);
+    }
+
+    #[test]
+    fn test_empty() {
+        assert_eq!("-".parse::<i8>().ok(), None);
+        assert_eq!("".parse::<u8>().ok(), None);
     }
 }