Skip to content

Commit 281de2c

Browse files
Auto merge of #149694 - lolbinarycat:alloc-extend-slice-of-str-spec, r=<try>
alloc: specialize String::extend for slices of str
2 parents 66428d9 + b17164a commit 281de2c

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

library/alloc/src/string.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,21 @@ impl String {
11051105
self.vec.extend_from_slice(string.as_bytes())
11061106
}
11071107

1108+
#[inline]
1109+
fn push_str_slice(&mut self, slice: &[&str]) {
1110+
let additional = slice.iter().map(|x| x.len()).sum();
1111+
self.reserve(additional);
1112+
let (ptr, len, cap) = core::mem::take(self).into_raw_parts();
1113+
unsafe {
1114+
let mut dst = ptr.add(len);
1115+
for new in slice {
1116+
core::ptr::copy_nonoverlapping(new.as_ptr(), dst, new.len());
1117+
dst = dst.add(new.len());
1118+
}
1119+
*self = String::from_raw_parts(ptr, len + additional, cap);
1120+
}
1121+
}
1122+
11081123
/// Copies elements from `src` range to the end of the string.
11091124
///
11101125
/// # Panics
@@ -2502,7 +2517,7 @@ impl<'a> Extend<&'a char> for String {
25022517
#[stable(feature = "rust1", since = "1.0.0")]
25032518
impl<'a> Extend<&'a str> for String {
25042519
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
2505-
iter.into_iter().for_each(move |s| self.push_str(s));
2520+
<I as SpecExtendStr>::spec_extend_into(iter, self)
25062521
}
25072522

25082523
#[inline]
@@ -2511,6 +2526,32 @@ impl<'a> Extend<&'a str> for String {
25112526
}
25122527
}
25132528

2529+
#[cfg(not(no_global_oom_handling))]
2530+
trait SpecExtendStr {
2531+
fn spec_extend_into(self, s: &mut String);
2532+
}
2533+
2534+
#[cfg(not(no_global_oom_handling))]
2535+
impl<'a, T: IntoIterator<Item = &'a str>> SpecExtendStr for T {
2536+
default fn spec_extend_into(self, target: &mut String) {
2537+
self.into_iter().for_each(move |s| target.push_str(s));
2538+
}
2539+
}
2540+
2541+
#[cfg(not(no_global_oom_handling))]
2542+
impl SpecExtendStr for [&str] {
2543+
fn spec_extend_into(self, target: &mut String) {
2544+
target.push_str_slice(&self);
2545+
}
2546+
}
2547+
2548+
#[cfg(not(no_global_oom_handling))]
2549+
impl<const N: usize> SpecExtendStr for [&str; N] {
2550+
fn spec_extend_into(self, target: &mut String) {
2551+
target.push_str_slice(&self[..]);
2552+
}
2553+
}
2554+
25142555
#[cfg(not(no_global_oom_handling))]
25152556
#[stable(feature = "box_str2", since = "1.45.0")]
25162557
impl<A: Allocator> Extend<Box<str, A>> for String {

0 commit comments

Comments
 (0)