From a8d78fec52aec04254ec602851c4fd7c8469c592 Mon Sep 17 00:00:00 2001 From: Thalia Archibald Date: Thu, 27 Feb 2025 23:38:19 -0800 Subject: 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` conflicts with `T: AsRef`, so stamp out string types with a macro. --- library/std/src/ffi/os_str.rs | 25 ++++++++++++++++++++++++- library/std/src/sys/os_str/bytes.rs | 5 +++++ library/std/src/sys/os_str/wtf8.rs | 5 +++++ 3 files changed, 34 insertions(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index f4a02802336..c0e659db307 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -257,7 +257,30 @@ impl OsString { #[inline] #[rustc_confusables("append", "put")] pub fn push>(&mut self, s: T) { - self.inner.push_slice(&s.as_ref().inner) + trait SpecPushTo { + fn spec_push_to(&self, buf: &mut OsString); + } + + impl> SpecPushTo for T { + #[inline] + default fn spec_push_to(&self, buf: &mut OsString) { + buf.inner.push_slice(&self.as_ref().inner); + } + } + + // Use a more efficient implementation when the string is UTF-8. + macro spec_str($T:ty) { + impl SpecPushTo for $T { + #[inline] + fn spec_push_to(&self, buf: &mut OsString) { + buf.inner.push_str(self); + } + } + } + spec_str!(str); + spec_str!(String); + + s.spec_push_to(self) } /// Creates a new `OsString` with at least the given capacity. diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index 1d337694944..dfff2d3e5d3 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -139,6 +139,11 @@ impl Buf { self.inner.extend_from_slice(&s.inner) } + #[inline] + pub fn push_str(&mut self, s: &str) { + self.inner.extend_from_slice(s.as_bytes()); + } + #[inline] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index 8acec6f949f..a32f5d40f6a 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -116,6 +116,11 @@ impl Buf { self.inner.push_wtf8(&s.inner) } + #[inline] + pub fn push_str(&mut self, s: &str) { + self.inner.push_str(s); + } + #[inline] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) -- cgit 1.4.1-3-g733a5