Skip to content

Commit c3c14e4

Browse files
committed
Implement int_from_ascii_radix
1 parent e960b5e commit c3c14e4

File tree

4 files changed

+63
-19
lines changed

4 files changed

+63
-19
lines changed

library/core/src/num/int_macros.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,34 @@ macro_rules! int_impl {
6363
/// ```
6464
#[stable(feature = "rust1", since = "1.0.0")]
6565
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
66-
from_str_radix(src, radix)
66+
from_ascii_radix(src.as_bytes(), radix)
67+
}
68+
69+
/// Parses an integer in a given base from a slice of bytes.
70+
///
71+
/// The bytes are interpreted as ASCII characters. Accepts an optional
72+
/// `+` or `-` sign followed by digits. Leading and trailing whitespace
73+
/// are rejected.
74+
/// Digits are a subset of these characters, depending on `radix`:
75+
///
76+
/// * `0-9`
77+
/// * `a-z`
78+
/// * `A-Z`
79+
///
80+
/// # Panics
81+
///
82+
/// This function panics if `radix` is not in the range from 2 to 36.
83+
///
84+
/// # Examples
85+
///
86+
/// ```
87+
/// #![feature(int_from_ascii_radix)]
88+
///
89+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_ascii_radix(b\"+100\", 2), Ok(4));")]
90+
/// ```
91+
#[unstable(feature = "int_from_ascii_radix", issue = "none")]
92+
pub fn from_ascii_radix(src: &[u8], radix: u32) -> Result<Self, ParseIntError> {
93+
from_ascii_radix(src, radix)
6794
}
6895

6996
/// Returns the number of ones in the binary representation of `self`.

library/core/src/num/mod.rs

+5-15
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ pub enum FpCategory {
10551055
}
10561056

10571057
#[doc(hidden)]
1058-
trait FromStrRadixHelper:
1058+
trait FromAsciiRadixHelper:
10591059
PartialOrd + Copy + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self>
10601060
{
10611061
const MIN: Self;
@@ -1071,15 +1071,15 @@ macro_rules! from_str_radix_int_impl {
10711071
impl FromStr for $t {
10721072
type Err = ParseIntError;
10731073
fn from_str(src: &str) -> Result<Self, ParseIntError> {
1074-
from_str_radix(src, 10)
1074+
from_ascii_radix(src.as_bytes(), 10)
10751075
}
10761076
}
10771077
)*}
10781078
}
10791079
from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
10801080

10811081
macro_rules! impl_helper_for {
1082-
($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
1082+
($($t:ty)*) => ($(impl FromAsciiRadixHelper for $t {
10831083
const MIN: Self = Self::MIN;
10841084
#[inline]
10851085
fn from_u32(u: u32) -> Self { u as Self }
@@ -1110,28 +1110,18 @@ pub fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> boo
11101110
radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
11111111
}
11121112

1113-
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
1113+
fn from_ascii_radix<T: FromAsciiRadixHelper>(src: &[u8], radix: u32) -> Result<T, ParseIntError> {
11141114
use self::IntErrorKind::*;
11151115
use self::ParseIntError as PIE;
11161116

1117-
assert!(
1118-
(2..=36).contains(&radix),
1119-
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
1120-
radix
1121-
);
1117+
assert!((2..=36).contains(&radix), "radix must lie in the range `[2, 36]` - found {}", radix);
11221118

11231119
if src.is_empty() {
11241120
return Err(PIE { kind: Empty });
11251121
}
11261122

11271123
let is_signed_ty = T::from_u32(0) > T::MIN;
11281124

1129-
// all valid digits are ascii, so we will just iterate over the utf8 bytes
1130-
// and cast them to chars. .to_digit() will safely return None for anything
1131-
// other than a valid ascii digit for the given radix, including the first-byte
1132-
// of multi-byte sequences
1133-
let src = src.as_bytes();
1134-
11351125
let (is_positive, digits) = match src[0] {
11361126
b'+' | b'-' if src[1..].is_empty() => {
11371127
return Err(PIE { kind: InvalidDigit });

library/core/src/num/nonzero.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::fmt;
44
use crate::ops::{BitOr, BitOrAssign, Div, Rem};
55
use crate::str::FromStr;
66

7-
use super::from_str_radix;
7+
use super::from_ascii_radix;
88
use super::{IntErrorKind, ParseIntError};
99
use crate::intrinsics;
1010

@@ -182,7 +182,7 @@ macro_rules! from_str_radix_nzint_impl {
182182
impl FromStr for $t {
183183
type Err = ParseIntError;
184184
fn from_str(src: &str) -> Result<Self, Self::Err> {
185-
Self::new(from_str_radix(src, 10)?)
185+
Self::new(from_ascii_radix(src.as_bytes(), 10)?)
186186
.ok_or(ParseIntError {
187187
kind: IntErrorKind::Zero
188188
})

library/core/src/num/uint_macros.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,34 @@ macro_rules! uint_impl {
6464
/// ```
6565
#[stable(feature = "rust1", since = "1.0.0")]
6666
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
67-
from_str_radix(src, radix)
67+
from_ascii_radix(src.as_bytes(), radix)
68+
}
69+
70+
/// Parses an integer in a given base from a slice of bytes.
71+
///
72+
/// The bytes are interpreted as ASCII characters. Accepts an
73+
/// optional `+` sign followed by digits. Leading and trailing
74+
/// whitespace are rejected.
75+
/// Digits are a subset of these characters, depending on `radix`:
76+
///
77+
/// * `0-9`
78+
/// * `a-z`
79+
/// * `A-Z`
80+
///
81+
/// # Panics
82+
///
83+
/// This function panics if `radix` is not in the range from 2 to 36.
84+
///
85+
/// # Examples
86+
///
87+
/// ```
88+
/// #![feature(int_from_ascii_radix)]
89+
///
90+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_ascii_radix(b\"+100\", 2), Ok(4));")]
91+
/// ```
92+
#[unstable(feature = "int_from_ascii_radix", issue = "none")]
93+
pub fn from_ascii_radix(src: &[u8], radix: u32) -> Result<Self, ParseIntError> {
94+
from_ascii_radix(src, radix)
6895
}
6996

7097
/// Returns the number of ones in the binary representation of `self`.

0 commit comments

Comments
 (0)