Skip to content

Implement int_from_ascii_radix #105206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,37 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
from_str_radix(src, radix)
from_ascii_radix(src.as_bytes(), radix)
}

/// Parses an integer in a given base from a slice of bytes.
///
/// The bytes are interpreted as ASCII characters. Accepts an optional
/// `+` or `-` sign followed by digits. Leading and trailing whitespace
/// are rejected.
/// Digits are a subset of these characters, depending on `radix`:
///
/// * `0-9`
/// * `a-z`
/// * `A-Z`
///
/// # Panics
///
/// This function panics if `radix` is not in the range from 2 to 36.
///
/// # Examples
///
/// ```
/// #![feature(int_from_ascii_radix)]
///
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_ascii_radix(b\"+100\", 2), Ok(4));")]
/// ```
#[unstable(feature = "int_from_ascii_radix", issue = "none")]
#[track_caller]
pub fn from_ascii_radix(src: &[u8], radix: u32) -> Result<Self, ParseIntError> {
from_ascii_radix(src, radix)
}

/// Returns the number of ones in the binary representation of `self`.
Expand Down
20 changes: 5 additions & 15 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,7 @@ pub enum FpCategory {
}

#[doc(hidden)]
trait FromStrRadixHelper:
trait FromAsciiRadixHelper:
PartialOrd + Copy + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self>
{
const MIN: Self;
Expand All @@ -1071,15 +1071,15 @@ macro_rules! from_str_radix_int_impl {
impl FromStr for $t {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, ParseIntError> {
from_str_radix(src, 10)
from_ascii_radix(src.as_bytes(), 10)
}
}
)*}
}
from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }

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

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

assert!(
(2..=36).contains(&radix),
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix
);
assert!((2..=36).contains(&radix), "radix 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;

// 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 the given radix, including the first-byte
// of multi-byte sequences
let src = src.as_bytes();

let (is_positive, digits) = match src[0] {
b'+' | b'-' if src[1..].is_empty() => {
return Err(PIE { kind: InvalidDigit });
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/num/nonzero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::fmt;
use crate::ops::{BitOr, BitOrAssign, Div, Rem};
use crate::str::FromStr;

use super::from_str_radix;
use super::from_ascii_radix;
use super::{IntErrorKind, ParseIntError};
use crate::intrinsics;

Expand Down Expand Up @@ -182,7 +182,7 @@ macro_rules! from_str_radix_nzint_impl {
impl FromStr for $t {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
Self::new(from_str_radix(src, 10)?)
Self::new(from_ascii_radix(src.as_bytes(), 10)?)
.ok_or(ParseIntError {
kind: IntErrorKind::Zero
})
Expand Down
31 changes: 30 additions & 1 deletion library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,37 @@ macro_rules! uint_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_str_radix(\"A\", 16), Ok(10));")]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, ParseIntError> {
from_str_radix(src, radix)
from_ascii_radix(src.as_bytes(), radix)
}

/// Parses an integer in a given base from a slice of bytes.
///
/// The bytes are interpreted as ASCII characters. Accepts an
/// optional `+` sign followed by digits. Leading and trailing
/// whitespace are rejected.
/// Digits are a subset of these characters, depending on `radix`:
///
/// * `0-9`
/// * `a-z`
/// * `A-Z`
///
/// # Panics
///
/// This function panics if `radix` is not in the range from 2 to 36.
///
/// # Examples
///
/// ```
/// #![feature(int_from_ascii_radix)]
///
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::from_ascii_radix(b\"+100\", 2), Ok(4));")]
/// ```
#[unstable(feature = "int_from_ascii_radix", issue = "none")]
#[track_caller]
pub fn from_ascii_radix(src: &[u8], radix: u32) -> Result<Self, ParseIntError> {
from_ascii_radix(src, radix)
}

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