Skip to content

Commit 4c170e1

Browse files
authored
Unrolled build for #160480
Rollup merge of #160480 - fereidani:to_ascii_upperlowercase, r=joshtriplett Single-pass ASCII lower/upper case conversion Current algorithm is cloning whole string/vector once, then rereads and rewrites it in-place once again which is sub-optimal and waste of CPU cycles and cache. This one creates it in a single-pass while copying the data from the original vector. In my benchmarks this one is about 1.2x-2x to 10x(KBs long strings) faster.
2 parents 1ed2df6 + 3d3bf13 commit 4c170e1

2 files changed

Lines changed: 10 additions & 12 deletions

File tree

library/alloc/src/slice.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -639,9 +639,7 @@ impl [u8] {
639639
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
640640
#[inline]
641641
pub fn to_ascii_uppercase(&self) -> Vec<u8> {
642-
let mut me = self.to_vec();
643-
me.make_ascii_uppercase();
644-
me
642+
self.iter().map(|b| b.to_ascii_uppercase()).collect()
645643
}
646644

647645
/// Returns a vector containing a copy of this slice where each byte
@@ -660,9 +658,7 @@ impl [u8] {
660658
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
661659
#[inline]
662660
pub fn to_ascii_lowercase(&self) -> Vec<u8> {
663-
let mut me = self.to_vec();
664-
me.make_ascii_lowercase();
665-
me
661+
self.iter().map(|b| b.to_ascii_lowercase()).collect()
666662
}
667663
}
668664

library/alloc/src/str.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -844,9 +844,10 @@ impl str {
844844
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
845845
#[inline]
846846
pub fn to_ascii_uppercase(&self) -> String {
847-
let mut s = self.to_owned();
848-
s.make_ascii_uppercase();
849-
s
847+
let bytes = self.as_bytes().to_ascii_uppercase();
848+
// SAFETY: ASCII case conversion only maps a-z to A-Z and leaves
849+
// all other bytes unchanged as valid UTF-8
850+
unsafe { String::from_utf8_unchecked(bytes) }
850851
}
851852

852853
/// Returns a copy of this string where each character is mapped to its
@@ -876,9 +877,10 @@ impl str {
876877
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
877878
#[inline]
878879
pub fn to_ascii_lowercase(&self) -> String {
879-
let mut s = self.to_owned();
880-
s.make_ascii_lowercase();
881-
s
880+
let bytes = self.as_bytes().to_ascii_lowercase();
881+
// SAFETY: ASCII case conversion only maps A-Z to a-z and leaves
882+
// all other bytes unchanged as valid UTF-8
883+
unsafe { String::from_utf8_unchecked(bytes) }
882884
}
883885
}
884886

0 commit comments

Comments
 (0)