diff --git a/lexical-parse-integer/src/algorithm.rs b/lexical-parse-integer/src/algorithm.rs index 7b2857fd..5f524101 100644 --- a/lexical-parse-integer/src/algorithm.rs +++ b/lexical-parse-integer/src/algorithm.rs @@ -742,7 +742,7 @@ macro_rules! algorithm { let mut value = T::ZERO; #[allow(unused_variables, unused_mut)] let mut has_suffix = false; - if cannot_overflow && is_negative { + if T::IS_SIGNED && cannot_overflow && is_negative { parse_digits_unchecked!( value, iter, @@ -753,7 +753,7 @@ macro_rules! algorithm { has_suffix, true, ); - } if cannot_overflow { + } else if cannot_overflow { parse_digits_unchecked!( value, iter, @@ -764,7 +764,7 @@ macro_rules! algorithm { has_suffix, true, ); - } else if is_negative { + } else if T::IS_SIGNED && is_negative { parse_digits_checked!( value, iter, diff --git a/lexical-util/src/num.rs b/lexical-util/src/num.rs index cd32dc62..5494dd94 100644 --- a/lexical-util/src/num.rs +++ b/lexical-util/src/num.rs @@ -686,15 +686,21 @@ pub trait Integer: !self.is_odd() } - /// Get the maximum number of digits before the slice will overflow. + /// Get the maximum number of digits before the slice could overflow. /// /// This is effectively the `floor(log(2^BITS-1, radix))`, but we can /// try to go a bit lower without worrying too much. #[inline(always)] fn overflow_digits(radix: u32) -> usize { // this is heavily optimized for base10 and it's a way under estimate - // that said, it's fast and works. - if radix <= 16 { + // that said, it's fast and works. the radix is **known** at compile + // time so we can optimize this further. + if cfg!(not(feature = "power-of-two")) || radix == 10 { + // NOTE: We generally want powers-of-two since it makes the comparison + // faster (it can just look for the upper bits being set), and luckily + // for radices of 10 we can always use `2 * bytes`. + mem::size_of::() * 2 + } else if radix <= 16 { mem::size_of::() * 2 - Self::IS_SIGNED as usize } else { // way under approximation but always works and is fast