Skip to content

Commit 12bd288

Browse files
committed
incorporate changes from code review
further reduce unsafe fn calls reduce right drift assert! sufficient capacity
1 parent d0d0885 commit 12bd288

File tree

2 files changed

+46
-38
lines changed

2 files changed

+46
-38
lines changed

src/liballoc/slice.rs

+13-11
Original file line numberDiff line numberDiff line change
@@ -567,17 +567,19 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
567567

568568
fn join(&self, sep: &T) -> Vec<T> {
569569
let mut iter = self.iter();
570-
iter.next().map_or(vec![], |first| {
571-
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
572-
let mut result = Vec::with_capacity(size + self.len());
573-
result.extend_from_slice(first.borrow());
574-
575-
for v in iter {
576-
result.push(sep.clone());
577-
result.extend_from_slice(v.borrow())
578-
}
579-
result
580-
})
570+
let first = match iter.next() {
571+
Some(first) => first,
572+
None => return vec![],
573+
};
574+
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
575+
let mut result = Vec::with_capacity(size + self.len());
576+
result.extend_from_slice(first.borrow());
577+
578+
for v in iter {
579+
result.push(sep.clone());
580+
result.extend_from_slice(v.borrow())
581+
}
582+
result
581583
}
582584

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

src/liballoc/str.rs

+33-27
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ macro_rules! spezialize_for_lengths {
130130
macro_rules! copy_slice_and_advance {
131131
($target:expr, $bytes:expr) => {
132132
let len = $bytes.len();
133-
$target.get_unchecked_mut(..len)
134-
.copy_from_slice($bytes);
135-
$target = {$target}.get_unchecked_mut(len..);
133+
let (head, tail) = {$target}.split_at_mut(len);
134+
head.copy_from_slice($bytes);
135+
$target = tail;
136136
}
137137
}
138138

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

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

169-
unsafe {
170-
result.extend_from_slice(first.borrow().as_ref());
176+
result.extend_from_slice(first.borrow().as_ref());
171177

172-
{
173-
let pos = result.len();
174-
let target = result.get_unchecked_mut(pos..len);
178+
unsafe {
179+
{
180+
let pos = result.len();
181+
let target = result.get_unchecked_mut(pos..len);
175182

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

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

0 commit comments

Comments
 (0)