diff options
| author | Giles Cope <gilescope@gmail.com> | 2022-04-02 11:13:44 +0100 |
|---|---|---|
| committer | Giles Cope <gilescope@gmail.com> | 2022-04-02 11:13:44 +0100 |
| commit | 72a5e7e810cbb2ea6db7ff37a599bc3826adee35 (patch) | |
| tree | a70bd55191f0450d45a2461294f09d6678ca28a0 | |
| parent | 4bfea7163781ebda2e7ade0faae9558ed812854d (diff) | |
| download | rust-72a5e7e810cbb2ea6db7ff37a599bc3826adee35.tar.gz rust-72a5e7e810cbb2ea6db7ff37a599bc3826adee35.zip | |
need guidence on testing
| -rw-r--r-- | library/core/src/num/mod.rs | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 5eb7b9096bc..12ab12d7ee0 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1035,6 +1035,11 @@ macro_rules! impl_helper_for { } impl_helper_for! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } +#[inline(always)] +pub(crate) fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits:&[u8]) -> bool { + 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> { use self::IntErrorKind::*; use self::ParseIntError as PIE; @@ -1068,7 +1073,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par let mut result = T::from_u32(0); - if radix <= 16 && digits.len() <= mem::size_of::<T>() * 2 - is_signed_ty as usize { + if can_not_overflow::<T>(radix, is_signed_ty, digits) { // SAFETY: If the len of the str is short compared to the range of the type // we are parsing into, then we can be certain that an overflow will not occur. // 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 run_unchecked_loop!(unchecked_sub) }; } - } else { + } else { macro_rules! run_checked_loop { - ($checked_additive_op:ident, $overflow_err:ident) => { + ($checked_additive_op:ident, $overflow_err:expr) => { for &c in digits { // When `radix` is passed in as a literal, rather than doing a slow `imul` // 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 let mul = result.checked_mul(radix); let x = (c as char).to_digit(radix).ok_or(PIE { kind: InvalidDigit })?; result = mul.ok_or_else($overflow_err)?; - result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?; + result = T::$checked_additive_op(&result, x).ok_or_else($overflow_err)?; } - } + }; } if is_positive { - let overflow_err = || PIE { kind: PosOverflow }; - run_checked_loop!(checked_add, overflow_err) + run_checked_loop!(checked_add, || PIE { kind: PosOverflow }) } else { - let overflow_err = || PIE { kind: NegOverflow }; - run_checked_loop!(checked_sub, overflow_err) + run_checked_loop!(checked_sub, || PIE { kind: NegOverflow }) }; } Ok(result) } + +mod tests { + #[test] + fn test_can_not_overflow() { + assert_eq!(can_not_overflow::<i8>(10, true, "99".as_bytes()), true); + assert_eq!(can_not_overflow::<i8>(10, true, "129".as_bytes()), false); + } +} \ No newline at end of file |
