summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-01-01 10:54:12 +0000
committerbors <bors@rust-lang.org>2025-01-01 10:54:12 +0000
commiteeeff9a66cda13934600800eee40fd84ba1647eb (patch)
tree0e616d296f4eb9fdd59852e22f4e04c838a31867 /library
parentbc3e3015b6e449bf1607f1023d2fbc2838ee37af (diff)
parentaa685bcccaa8fdb187e68de29f35db11aa99630f (diff)
downloadrust-eeeff9a66cda13934600800eee40fd84ba1647eb.tar.gz
rust-eeeff9a66cda13934600800eee40fd84ba1647eb.zip
Auto merge of #134969 - Marcondiro:master, r=jhpratt,programmerjake
char to_digit: avoid unnecessary casts to u64

Hello,
in the `char::to_digit` method there are a few `as u64` casts that are not strictly necessary.
I assume that the reason behind these casts is to avoid possible overflows in the `+ 10` add.

This PR removes the aforementioned casts, avoiding the overflow issue by slightly modifying the ASCII letter to int mapping.

Thanks,
Happy new year.
Diffstat (limited to 'library')
-rw-r--r--library/core/src/char/methods.rs18
1 files changed, 11 insertions, 7 deletions
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 7d33765879f..fb8a740aced 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -394,17 +394,21 @@ impl char {
         );
         // check radix to remove letter handling code when radix is a known constant
         let value = if self > '9' && radix > 10 {
-            // convert ASCII letters to lowercase
-            let lower = self as u32 | 0x20;
-            // convert an ASCII letter to the corresponding value,
-            // non-letters convert to values > 36
-            lower.wrapping_sub('a' as u32) as u64 + 10
+            // mask to convert ASCII letters to uppercase
+            const TO_UPPERCASE_MASK: u32 = !0b0010_0000;
+            // Converts an ASCII letter to its corresponding integer value:
+            // A-Z => 10-35, a-z => 10-35. Other characters produce values >= 36.
+            //
+            // Add Overflow Safety:
+            // By applying the mask after the subtraction, the first addendum is
+            // constrained such that it never exceeds u32::MAX - 0x20.
+            ((self as u32).wrapping_sub('A' as u32) & TO_UPPERCASE_MASK) + 10
         } else {
             // convert digit to value, non-digits wrap to values > 36
-            (self as u32).wrapping_sub('0' as u32) as u64
+            (self as u32).wrapping_sub('0' as u32)
         };
         // FIXME(const-hack): once then_some is const fn, use it here
-        if value < radix as u64 { Some(value as u32) } else { None }
+        if value < radix { Some(value) } else { None }
     }
 
     /// Returns an iterator that yields the hexadecimal Unicode escape of a