Skip to content

Commit b17164a

Browse files
committed
alloc: specialize String::extend for slices of str
1 parent fa8eb7e commit b17164a

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
@@ -1097,6 +1097,21 @@ impl String {
10971097
self.vec.extend_from_slice(string.as_bytes())
10981098
}
10991099

1100+
#[inline]
1101+
fn push_str_slice(&mut self, slice: &[&str]) {
1102+
let additional = slice.iter().map(|x| x.len()).sum();
1103+
self.reserve(additional);
1104+
let (ptr, len, cap) = core::mem::take(self).into_raw_parts();
1105+
unsafe {
1106+
let mut dst = ptr.add(len);
1107+
for new in slice {
1108+
core::ptr::copy_nonoverlapping(new.as_ptr(), dst, new.len());
1109+
dst = dst.add(new.len());
1110+
}
1111+
*self = String::from_raw_parts(ptr, len + additional, cap);
1112+
}
1113+
}
1114+
11001115
/// Copies elements from `src` range to the end of the string.
11011116
///
11021117
/// # Panics
@@ -2489,7 +2504,7 @@ impl<'a> Extend<&'a char> for String {
24892504
#[stable(feature = "rust1", since = "1.0.0")]
24902505
impl<'a> Extend<&'a str> for String {
24912506
fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
2492-
iter.into_iter().for_each(move |s| self.push_str(s));
2507+
<I as SpecExtendStr>::spec_extend_into(iter, self)
24932508
}
24942509

24952510
#[inline]
@@ -2498,6 +2513,32 @@ impl<'a> Extend<&'a str> for String {
24982513
}
24992514
}
25002515

2516+
#[cfg(not(no_global_oom_handling))]
2517+
trait SpecExtendStr {
2518+
fn spec_extend_into(self, s: &mut String);
2519+
}
2520+
2521+
#[cfg(not(no_global_oom_handling))]
2522+
impl<'a, T: IntoIterator<Item = &'a str>> SpecExtendStr for T {
2523+
default fn spec_extend_into(self, target: &mut String) {
2524+
self.into_iter().for_each(move |s| target.push_str(s));
2525+
}
2526+
}
2527+
2528+
#[cfg(not(no_global_oom_handling))]
2529+
impl SpecExtendStr for [&str] {
2530+
fn spec_extend_into(self, target: &mut String) {
2531+
target.push_str_slice(&self);
2532+
}
2533+
}
2534+
2535+
#[cfg(not(no_global_oom_handling))]
2536+
impl<const N: usize> SpecExtendStr for [&str; N] {
2537+
fn spec_extend_into(self, target: &mut String) {
2538+
target.push_str_slice(&self[..]);
2539+
}
2540+
}
2541+
25012542
#[cfg(not(no_global_oom_handling))]
25022543
#[stable(feature = "box_str2", since = "1.45.0")]
25032544
impl<A: Allocator> Extend<Box<str, A>> for String {

0 commit comments

Comments
 (0)