5
5
use crate :: ascii;
6
6
use crate :: intrinsics;
7
7
use crate :: mem;
8
+ use crate :: ops:: { Add , Mul , Sub } ;
8
9
use crate :: str:: FromStr ;
9
10
10
11
// Used because the `?` operator is not allowed in a const context.
@@ -969,14 +970,14 @@ pub enum FpCategory {
969
970
}
970
971
971
972
#[ doc( hidden) ]
972
- trait FromStrRadixHelper : PartialOrd + Copy + Default {
973
+ trait FromStrRadixHelper :
974
+ PartialOrd + Copy + Default + Add < Output = Self > + Sub < Output = Self > + Mul < Output = Self >
975
+ {
973
976
const MIN : Self ;
977
+ fn from_u32 ( u : u32 ) -> Self ;
974
978
fn checked_mul ( & self , other : u32 ) -> Option < Self > ;
975
979
fn checked_sub ( & self , other : u32 ) -> Option < Self > ;
976
980
fn checked_add ( & self , other : u32 ) -> Option < Self > ;
977
- unsafe fn unchecked_mul ( self , other : u32 ) -> Self ;
978
- unsafe fn unchecked_sub ( self , other : u32 ) -> Self ;
979
- unsafe fn unchecked_add ( self , other : u32 ) -> Self ;
980
981
}
981
982
982
983
macro_rules! from_str_radix_int_impl {
@@ -996,6 +997,8 @@ macro_rules! impl_helper_for {
996
997
( $( $t: ty) * ) => ( $( impl FromStrRadixHelper for $t {
997
998
const MIN : Self = Self :: MIN ;
998
999
#[ inline]
1000
+ fn from_u32( u: u32 ) -> Self { u as Self }
1001
+ #[ inline]
999
1002
fn checked_mul( & self , other: u32 ) -> Option <Self > {
1000
1003
Self :: checked_mul( * self , other as Self )
1001
1004
}
@@ -1007,27 +1010,6 @@ macro_rules! impl_helper_for {
1007
1010
fn checked_add( & self , other: u32 ) -> Option <Self > {
1008
1011
Self :: checked_add( * self , other as Self )
1009
1012
}
1010
- #[ inline]
1011
- unsafe fn unchecked_mul( self , other: u32 ) -> Self {
1012
- // SAFETY: Conditions of `Self::unchecked_mul` must be upheld by the caller.
1013
- unsafe {
1014
- Self :: unchecked_mul( self , other as Self )
1015
- }
1016
- }
1017
- #[ inline]
1018
- unsafe fn unchecked_sub( self , other: u32 ) -> Self {
1019
- // SAFETY: Conditions of `Self::unchecked_sub` must be upheld by the caller.
1020
- unsafe {
1021
- Self :: unchecked_sub( self , other as Self )
1022
- }
1023
- }
1024
- #[ inline]
1025
- unsafe fn unchecked_add( self , other: u32 ) -> Self {
1026
- // SAFETY: Conditions of `Self::unchecked_add` must be upheld by the caller.
1027
- unsafe {
1028
- Self :: unchecked_add( self , other as Self )
1029
- }
1030
- }
1031
1013
} ) * )
1032
1014
}
1033
1015
impl_helper_for ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
@@ -1077,30 +1059,28 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
1077
1059
let mut result = T :: default ( ) ;
1078
1060
1079
1061
if can_not_overflow :: < T > ( radix, is_signed_ty, digits) {
1080
- // SAFETY: If the len of the str is short compared to the range of the type
1062
+ // If the len of the str is short compared to the range of the type
1081
1063
// we are parsing into, then we can be certain that an overflow will not occur.
1082
1064
// This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition
1083
1065
// above is a faster (conservative) approximation of this.
1084
1066
//
1085
1067
// Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest:
1086
1068
// `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
1087
1069
// `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
1088
- unsafe {
1089
- macro_rules! run_unchecked_loop {
1090
- ( $unchecked_additive_op: ident) => {
1091
- for & c in digits {
1092
- result = result. unchecked_mul( radix) ;
1093
- let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1094
- result = T :: $unchecked_additive_op( result, x) ;
1095
- }
1096
- } ;
1097
- }
1098
- if is_positive {
1099
- run_unchecked_loop ! ( unchecked_add)
1100
- } else {
1101
- run_unchecked_loop ! ( unchecked_sub)
1070
+ macro_rules! run_unchecked_loop {
1071
+ ( $unchecked_additive_op: expr) => {
1072
+ for & c in digits {
1073
+ result = result * T :: from_u32( radix) ;
1074
+ let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1075
+ result = $unchecked_additive_op( result, T :: from_u32( x) ) ;
1076
+ }
1102
1077
} ;
1103
1078
}
1079
+ if is_positive {
1080
+ run_unchecked_loop ! ( <T as core:: ops:: Add >:: add)
1081
+ } else {
1082
+ run_unchecked_loop ! ( <T as core:: ops:: Sub >:: sub)
1083
+ } ;
1104
1084
} else {
1105
1085
macro_rules! run_checked_loop {
1106
1086
( $checked_additive_op: ident, $overflow_err: expr) => {
0 commit comments