Skip to content

Commit 72a5e7e

Browse files
committed
need guidence on testing
1 parent 4bfea71 commit 72a5e7e

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

library/core/src/num/mod.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,11 @@ macro_rules! impl_helper_for {
10351035
}
10361036
impl_helper_for! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
10371037

1038+
#[inline(always)]
1039+
pub(crate) fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits:&[u8]) -> bool {
1040+
radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize
1041+
}
1042+
10381043
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
10391044
use self::IntErrorKind::*;
10401045
use self::ParseIntError as PIE;
@@ -1068,7 +1073,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10681073

10691074
let mut result = T::from_u32(0);
10701075

1071-
if radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize {
1076+
if can_not_overflow::<T>(radix, is_signed_ty, digits) {
10721077
// SAFETY: If the len of the str is short compared to the range of the type
10731078
// we are parsing into, then we can be certain that an overflow will not occur.
10741079
// This bound is when `radix.pow(digits.len()) - 1 <= T::MAX` but the condition
@@ -1093,9 +1098,9 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10931098
run_unchecked_loop!(unchecked_sub)
10941099
};
10951100
}
1096-
} else {
1101+
} else {
10971102
macro_rules! run_checked_loop {
1098-
($checked_additive_op:ident, $overflow_err:ident) => {
1103+
($checked_additive_op:ident, $overflow_err:expr) => {
10991104
for &c in digits {
11001105
// When `radix` is passed in as a literal, rather than doing a slow `imul`
11011106
// the compiler can use shifts if `radix` can be expressed as a
@@ -1110,17 +1115,23 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
11101115
let mul = result.checked_mul(radix);
11111116
let x = (c as char).to_digit(radix).ok_or(PIE { kind: InvalidDigit })?;
11121117
result = mul.ok_or_else($overflow_err)?;
1113-
result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?;
1118+
result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?;
11141119
}
1115-
}
1120+
};
11161121
}
11171122
if is_positive {
1118-
let overflow_err = || PIE { kind: PosOverflow };
1119-
run_checked_loop!(checked_add, overflow_err)
1123+
run_checked_loop!(checked_add, || PIE { kind: PosOverflow })
11201124
} else {
1121-
let overflow_err = || PIE { kind: NegOverflow };
1122-
run_checked_loop!(checked_sub, overflow_err)
1125+
run_checked_loop!(checked_sub, || PIE { kind: NegOverflow })
11231126
};
11241127
}
11251128
Ok(result)
11261129
}
1130+
1131+
mod tests {
1132+
#[test]
1133+
fn test_can_not_overflow() {
1134+
assert_eq!(can_not_overflow::<i8>(10, true, "99".as_bytes()), true);
1135+
assert_eq!(can_not_overflow::<i8>(10, true, "129".as_bytes()), false);
1136+
}
1137+
}

0 commit comments

Comments
 (0)