Skip to content

Commit b6401ed

Browse files
committed
Specialize OsString::push for strings
When concatenating two WTF-8 strings, surrogate pairs at the boundaries need to be joined. However, since UTF-8 strings cannot contain surrogate halves, this check can be skipped when one string is UTF-8. Specialize `OsString::push` to use a more efficient concatenation in this case. Unfortunately, a specialization for `T: AsRef<str>` conflicts with `T: AsRef<OsStr>`, so stamp out string types with a macro.
1 parent 655937c commit b6401ed

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

std/src/ffi/os_str.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,30 @@ impl OsString {
257257
#[inline]
258258
#[rustc_confusables("append", "put")]
259259
pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
260-
self.inner.push_slice(&s.as_ref().inner)
260+
trait SpecPushTo {
261+
fn spec_push_to(&self, buf: &mut OsString);
262+
}
263+
264+
impl<T: AsRef<OsStr>> SpecPushTo for T {
265+
#[inline]
266+
default fn spec_push_to(&self, buf: &mut OsString) {
267+
buf.inner.push_slice(&self.as_ref().inner);
268+
}
269+
}
270+
271+
// Use a more efficient implementation when the string is UTF-8.
272+
macro spec_str($T:ty) {
273+
impl SpecPushTo for $T {
274+
#[inline]
275+
fn spec_push_to(&self, buf: &mut OsString) {
276+
buf.inner.push_str(self);
277+
}
278+
}
279+
}
280+
spec_str!(str);
281+
spec_str!(String);
282+
283+
s.spec_push_to(self)
261284
}
262285

263286
/// Creates a new `OsString` with at least the given capacity.

std/src/sys/os_str/bytes.rs

+5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ impl Buf {
139139
self.inner.extend_from_slice(&s.inner)
140140
}
141141

142+
#[inline]
143+
pub fn push_str(&mut self, s: &str) {
144+
self.inner.extend_from_slice(s.as_bytes());
145+
}
146+
142147
#[inline]
143148
pub fn reserve(&mut self, additional: usize) {
144149
self.inner.reserve(additional)

std/src/sys/os_str/wtf8.rs

+5
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ impl Buf {
116116
self.inner.push_wtf8(&s.inner)
117117
}
118118

119+
#[inline]
120+
pub fn push_str(&mut self, s: &str) {
121+
self.inner.push_str(s);
122+
}
123+
119124
#[inline]
120125
pub fn reserve(&mut self, additional: usize) {
121126
self.inner.reserve(additional)

0 commit comments

Comments
 (0)