@@ -975,9 +975,9 @@ trait FromStrRadixHelper: PartialOrd + Copy {
975
975
fn checked_mul ( & self , other : u32 ) -> Option < Self > ;
976
976
fn checked_sub ( & self , other : u32 ) -> Option < Self > ;
977
977
fn checked_add ( & self , other : u32 ) -> Option < Self > ;
978
- unsafe fn unchecked_mul ( & self , other : u32 ) -> Self ;
979
- unsafe fn unchecked_sub ( & self , other : u32 ) -> Self ;
980
- unsafe fn unchecked_add ( & self , other : u32 ) -> Self ;
978
+ unsafe fn unchecked_mul ( self , other : u32 ) -> Self ;
979
+ unsafe fn unchecked_sub ( self , other : u32 ) -> Self ;
980
+ unsafe fn unchecked_add ( self , other : u32 ) -> Self ;
981
981
}
982
982
983
983
macro_rules! from_str_radix_int_impl {
@@ -993,7 +993,7 @@ macro_rules! from_str_radix_int_impl {
993
993
}
994
994
from_str_radix_int_impl ! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
995
995
996
- macro_rules! doit {
996
+ macro_rules! impl_helper_for {
997
997
( $( $t: ty) * ) => ( $( impl FromStrRadixHelper for $t {
998
998
const MIN : Self = Self :: MIN ;
999
999
#[ inline]
@@ -1011,29 +1011,29 @@ macro_rules! doit {
1011
1011
Self :: checked_add( * self , other as Self )
1012
1012
}
1013
1013
#[ inline]
1014
- unsafe fn unchecked_mul( & self , other: u32 ) -> Self {
1014
+ unsafe fn unchecked_mul( self , other: u32 ) -> Self {
1015
1015
// SAFETY: Conditions of `Self::unchecked_mul` must be upheld by the caller.
1016
1016
unsafe {
1017
- Self :: unchecked_mul( * self , other as Self )
1017
+ Self :: unchecked_mul( self , other as Self )
1018
1018
}
1019
1019
}
1020
1020
#[ inline]
1021
- unsafe fn unchecked_sub( & self , other: u32 ) -> Self {
1021
+ unsafe fn unchecked_sub( self , other: u32 ) -> Self {
1022
1022
// SAFETY: Conditions of `Self::unchecked_sub` must be upheld by the caller.
1023
1023
unsafe {
1024
- Self :: unchecked_sub( * self , other as Self )
1024
+ Self :: unchecked_sub( self , other as Self )
1025
1025
}
1026
1026
}
1027
1027
#[ inline]
1028
- unsafe fn unchecked_add( & self , other: u32 ) -> Self {
1028
+ unsafe fn unchecked_add( self , other: u32 ) -> Self {
1029
1029
// SAFETY: Conditions of `Self::unchecked_add` must be upheld by the caller.
1030
1030
unsafe {
1031
- Self :: unchecked_add( * self , other as Self )
1031
+ Self :: unchecked_add( self , other as Self )
1032
1032
}
1033
1033
}
1034
1034
} ) * )
1035
1035
}
1036
- doit ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
1036
+ impl_helper_for ! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
1037
1037
1038
1038
fn from_str_radix < T : FromStrRadixHelper > ( src : & str , radix : u32 ) -> Result < T , ParseIntError > {
1039
1039
use self :: IntErrorKind :: * ;
@@ -1078,41 +1078,49 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
1078
1078
// `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
1079
1079
// `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
1080
1080
unsafe {
1081
- macro_rules! run_loop {
1081
+ macro_rules! run_unchecked_loop {
1082
1082
( $unchecked_additive_op: ident) => {
1083
1083
for & c in digits {
1084
1084
result = result. unchecked_mul( radix) ;
1085
1085
let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1086
- result = T :: $unchecked_additive_op( & result, x) ;
1086
+ result = T :: $unchecked_additive_op( result, x) ;
1087
1087
}
1088
1088
} ;
1089
1089
}
1090
1090
if is_positive {
1091
- run_loop ! ( unchecked_add)
1091
+ run_unchecked_loop ! ( unchecked_add)
1092
1092
} else {
1093
- run_loop ! ( unchecked_sub)
1093
+ run_unchecked_loop ! ( unchecked_sub)
1094
1094
} ;
1095
1095
}
1096
- } else {
1097
- let additive_op = if is_positive { T :: checked_add } else { T :: checked_sub } ;
1098
- let overflow_err = || PIE { kind : if is_positive { PosOverflow } else { NegOverflow } } ;
1099
-
1100
- for & c in digits {
1101
- // When `radix` is passed in as a literal, rather than doing a slow `imul`
1102
- // the compiler can use shifts if `radix` can be expressed as a
1103
- // sum of powers of 2 (x*10 can be written as x*8 + x*2).
1104
- // When the compiler can't use these optimisations,
1105
- // the latency of the multiplication can be hidden by issuing it
1106
- // before the result is needed to improve performance on
1107
- // modern out-of-order CPU as multiplication here is slower
1108
- // than the other instructions, we can get the end result faster
1109
- // doing multiplication first and let the CPU spends other cycles
1110
- // doing other computation and get multiplication result later.
1111
- let mul = result. checked_mul ( radix) ;
1112
- let x = ( c as char ) . to_digit ( radix) . ok_or ( PIE { kind : InvalidDigit } ) ?;
1113
- result = mul. ok_or_else ( overflow_err) ?;
1114
- result = additive_op ( & result, x) . ok_or_else ( overflow_err) ?;
1096
+ } else {
1097
+ macro_rules! run_checked_loop {
1098
+ ( $checked_additive_op: ident, $overflow_err: ident) => {
1099
+ for & c in digits {
1100
+ // When `radix` is passed in as a literal, rather than doing a slow `imul`
1101
+ // the compiler can use shifts if `radix` can be expressed as a
1102
+ // sum of powers of 2 (x*10 can be written as x*8 + x*2).
1103
+ // When the compiler can't use these optimisations,
1104
+ // the latency of the multiplication can be hidden by issuing it
1105
+ // before the result is needed to improve performance on
1106
+ // modern out-of-order CPU as multiplication here is slower
1107
+ // than the other instructions, we can get the end result faster
1108
+ // doing multiplication first and let the CPU spends other cycles
1109
+ // doing other computation and get multiplication result later.
1110
+ let mul = result. checked_mul( radix) ;
1111
+ let x = ( c as char ) . to_digit( radix) . ok_or( PIE { kind: InvalidDigit } ) ?;
1112
+ result = mul. ok_or_else( $overflow_err) ?;
1113
+ result = T :: $checked_additive_op( & result, x) . ok_or_else( $overflow_err) ?;
1114
+ }
1115
+ }
1115
1116
}
1117
+ if is_positive {
1118
+ let overflow_err = || PIE { kind : PosOverflow } ;
1119
+ run_checked_loop ! ( checked_add, overflow_err)
1120
+ } else {
1121
+ let overflow_err = || PIE { kind : NegOverflow } ;
1122
+ run_checked_loop ! ( checked_sub, overflow_err)
1123
+ } ;
1116
1124
}
1117
1125
Ok ( result)
1118
1126
}
0 commit comments