diff options
| author | Thalia Archibald <thalia@archibald.dev> | 2025-02-27 23:38:19 -0800 |
|---|---|---|
| committer | Thalia Archibald <thalia@archibald.dev> | 2025-02-28 13:42:31 -0800 |
| commit | a8d78fec52aec04254ec602851c4fd7c8469c592 (patch) | |
| tree | 1f81103ee010f69901f5491475f70100e980888b /library/std/src | |
| parent | 287487624357c19b22d27aa3ed584b8ccd080b4d (diff) | |
| download | rust-a8d78fec52aec04254ec602851c4fd7c8469c592.tar.gz rust-a8d78fec52aec04254ec602851c4fd7c8469c592.zip | |
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.
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/ffi/os_str.rs | 25 | ||||
| -rw-r--r-- | library/std/src/sys/os_str/bytes.rs | 5 | ||||
| -rw-r--r-- | library/std/src/sys/os_str/wtf8.rs | 5 |
3 files changed, 34 insertions, 1 deletions
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<T: AsRef<OsStr>>(&mut self, s: T) { - self.inner.push_slice(&s.as_ref().inner) + trait SpecPushTo { + fn spec_push_to(&self, buf: &mut OsString); + } + + impl<T: AsRef<OsStr>> 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 @@ -140,6 +140,11 @@ impl Buf { } #[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 @@ -117,6 +117,11 @@ impl Buf { } #[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) } |
