Skip to content

Commit 6d0c5b8

Browse files
committed
incorporate changes from code review
further reduce unsafe fn calls reduce right drift assert! sufficient capacity
1 parent fa2855e commit 6d0c5b8

File tree

2 files changed

+46
-38
lines changed

2 files changed

+46
-38
lines changed

src/liballoc/slice.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -576,17 +576,19 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
576576

577577
fn join(&self, sep: &T) -> Vec<T> {
578578
let mut iter = self.iter();
579-
iter.next().map_or(vec![], |first| {
580-
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
581-
let mut result = Vec::with_capacity(size + self.len());
582-
result.extend_from_slice(first.borrow());
583-
584-
for v in iter {
585-
result.push(sep.clone());
586-
result.extend_from_slice(v.borrow())
587-
}
588-
result
589-
})
579+
let first = match iter.next() {
580+
Some(first) => first,
581+
None => return vec![],
582+
};
583+
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
584+
let mut result = Vec::with_capacity(size + self.len());
585+
result.extend_from_slice(first.borrow());
586+
587+
for v in iter {
588+
result.push(sep.clone());
589+
result.extend_from_slice(v.borrow())
590+
}
591+
result
590592
}
591593

592594
fn connect(&self, sep: &T) -> Vec<T> {

src/liballoc/str.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ macro_rules! spezialize_for_lengths {
131131
macro_rules! copy_slice_and_advance {
132132
($target:expr, $bytes:expr) => {
133133
let len = $bytes.len();
134-
$target.get_unchecked_mut(..len)
135-
.copy_from_slice($bytes);
136-
$target = {$target}.get_unchecked_mut(len..);
134+
let (head, tail) = {$target}.split_at_mut(len);
135+
head.copy_from_slice($bytes);
136+
$target = tail;
137137
}
138138
}
139139

@@ -153,36 +153,42 @@ where
153153
{
154154
let sep_len = sep.len();
155155
let mut iter = slice.iter();
156-
iter.next().map_or(vec![], |first| {
157-
// this is wrong without the guarantee that `slice` is non-empty
158-
// if the `len` calculation overflows, we'll panic
159-
// we would have run out of memory anyway and the rest of the function requires
160-
// the entire String pre-allocated for safety
161-
//
162-
// this is the exact len of the resulting String
163-
let len = sep_len.checked_mul(slice.len() - 1).and_then(|n| {
164-
slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add)
156+
157+
// the first slice is the only one without a separator preceding it
158+
let first = match iter.next() {
159+
Some(first) => first,
160+
None => return vec![],
161+
};
162+
163+
// compute the exact total length of the joined Vec
164+
// if the `len` calculation overflows, we'll panic
165+
// we would have run out of memory anyway and the rest of the function requires
166+
// the entire Vec pre-allocated for safety
167+
let len = sep_len.checked_mul(iter.len()).and_then(|n| {
168+
slice.iter()
169+
.map(|s| s.borrow().as_ref().len())
170+
.try_fold(n, usize::checked_add)
165171
}).expect("attempt to join into collection with len > usize::MAX");
166172

167-
// crucial for safety
168-
let mut result = Vec::with_capacity(len);
173+
// crucial for safety
174+
let mut result = Vec::with_capacity(len);
175+
assert!(result.capacity() >= len);
169176

170-
unsafe {
171-
result.extend_from_slice(first.borrow().as_ref());
177+
result.extend_from_slice(first.borrow().as_ref());
172178

173-
{
174-
let pos = result.len();
175-
let target = result.get_unchecked_mut(pos..len);
179+
unsafe {
180+
{
181+
let pos = result.len();
182+
let target = result.get_unchecked_mut(pos..len);
176183

177-
// copy separator and strs over without bounds checks
178-
// generate loops with hardcoded offsets for small separators
179-
// massive improvements possible (~ x2)
180-
spezialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
181-
}
182-
result.set_len(len);
184+
// copy separator and slices over without bounds checks
185+
// generate loops with hardcoded offsets for small separators
186+
// massive improvements possible (~ x2)
187+
spezialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4);
183188
}
184-
result
185-
})
189+
result.set_len(len);
190+
}
191+
result
186192
}
187193

188194
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)