Skip to content

Commit 82fd262

Browse files
author
bors-servo
authored
Auto merge of #189 - servo:stack-case, r=nox
Avoid some allocations in to_ascii_{upper,lower}case <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/string-cache/189) <!-- Reviewable:end -->
2 parents bdeaac5 + 830835a commit 82fd262

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
name = "string_cache"
4-
version = "0.5.1" # Also update README.md when making a semver-breaking change
4+
version = "0.5.2" # Also update README.md when making a semver-breaking change
55
authors = [ "The Servo Project Developers" ]
66
description = "A string interning library for Rust, developed as part of the Servo project."
77
license = "MIT / Apache-2.0"

src/atom.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,19 +469,37 @@ impl<Static: StaticAtomSet> Deserialize for Atom<Static> {
469469
// We don't need to implement is_ascii because there's no performance improvement
470470
// over the one from &str.
471471
impl<Static: StaticAtomSet> Atom<Static> {
472+
fn from_mutated_str<F: FnOnce(&mut str)>(s: &str, f: F) -> Self {
473+
let mut buffer: [u8; 64] = unsafe { mem::uninitialized() };
474+
if let Some(buffer_prefix) = buffer.get_mut(..s.len()) {
475+
buffer_prefix.copy_from_slice(s.as_bytes());
476+
// FIXME: use from std::str when stable https://github.com/rust-lang/rust/issues/41119
477+
pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
478+
mem::transmute(v)
479+
}
480+
let as_str = unsafe { from_utf8_unchecked_mut(buffer_prefix) };
481+
f(as_str);
482+
Atom::from(&*as_str)
483+
} else {
484+
let mut string = s.to_owned();
485+
f(&mut string);
486+
Atom::from(string)
487+
}
488+
}
489+
472490
pub fn to_ascii_uppercase(&self) -> Self {
473-
for b in self.bytes() {
491+
for (i, b) in self.bytes().enumerate() {
474492
if let b'a' ... b'z' = b {
475-
return Atom::from((&**self).to_ascii_uppercase())
493+
return Atom::from_mutated_str(self, |s| s[i..].make_ascii_uppercase())
476494
}
477495
}
478496
self.clone()
479497
}
480498

481499
pub fn to_ascii_lowercase(&self) -> Self {
482-
for b in self.bytes() {
500+
for (i, b) in self.bytes().enumerate() {
483501
if let b'A' ... b'Z' = b {
484-
return Atom::from((&**self).to_ascii_lowercase())
502+
return Atom::from_mutated_str(self, |s| s[i..].make_ascii_lowercase())
485503
}
486504
}
487505
self.clone()

0 commit comments

Comments
 (0)