vec: Write the .extend() specialization in cleaner style
As far as possible, use regular `default fn` specialization in favour of ad-hoc conditionals.
This commit is contained in:
parent
c9f16bbc41
commit
5058e58676
1 changed files with 41 additions and 30 deletions
|
|
@ -1586,36 +1586,34 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
|
|||
impl<T> Extend<T> for Vec<T> {
|
||||
#[inline]
|
||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
self.extend_desugared(iter.into_iter())
|
||||
self.spec_extend(iter.into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
trait IsTrustedLen : Iterator {
|
||||
fn trusted_len(&self) -> Option<usize> { None }
|
||||
trait SpecExtend<I> {
|
||||
fn spec_extend(&mut self, iter: I);
|
||||
}
|
||||
impl<I> IsTrustedLen for I where I: Iterator { }
|
||||
|
||||
impl<I> IsTrustedLen for I where I: TrustedLen
|
||||
impl<I, T> SpecExtend<I> for Vec<T>
|
||||
where I: Iterator<Item=T>,
|
||||
{
|
||||
fn trusted_len(&self) -> Option<usize> {
|
||||
let (low, high) = self.size_hint();
|
||||
default fn spec_extend(&mut self, iter: I) {
|
||||
self.extend_desugared(iter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, T> SpecExtend<I> for Vec<T>
|
||||
where I: TrustedLen<Item=T>,
|
||||
{
|
||||
fn spec_extend(&mut self, iterator: I) {
|
||||
// This is the case for a TrustedLen iterator.
|
||||
let (low, high) = iterator.size_hint();
|
||||
if let Some(high_value) = high {
|
||||
debug_assert_eq!(low, high_value,
|
||||
"TrustedLen iterator's size hint is not exact: {:?}",
|
||||
(low, high));
|
||||
}
|
||||
high
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
|
||||
// This function should be the moral equivalent of:
|
||||
//
|
||||
// for item in iterator {
|
||||
// self.push(item);
|
||||
// }
|
||||
if let Some(additional) = iterator.trusted_len() {
|
||||
if let Some(additional) = high {
|
||||
self.reserve(additional);
|
||||
unsafe {
|
||||
let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
|
||||
|
|
@ -1628,17 +1626,30 @@ impl<T> Vec<T> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
while let Some(element) = iterator.next() {
|
||||
let len = self.len();
|
||||
if len == self.capacity() {
|
||||
let (lower, _) = iterator.size_hint();
|
||||
self.reserve(lower.saturating_add(1));
|
||||
}
|
||||
unsafe {
|
||||
ptr::write(self.get_unchecked_mut(len), element);
|
||||
// NB can't overflow since we would have had to alloc the address space
|
||||
self.set_len(len + 1);
|
||||
}
|
||||
self.extend_desugared(iterator)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
|
||||
// This is the case for a general iterator.
|
||||
//
|
||||
// This function should be the moral equivalent of:
|
||||
//
|
||||
// for item in iterator {
|
||||
// self.push(item);
|
||||
// }
|
||||
while let Some(element) = iterator.next() {
|
||||
let len = self.len();
|
||||
if len == self.capacity() {
|
||||
let (lower, _) = iterator.size_hint();
|
||||
self.reserve(lower.saturating_add(1));
|
||||
}
|
||||
unsafe {
|
||||
ptr::write(self.get_unchecked_mut(len), element);
|
||||
// NB can't overflow since we would have had to alloc the address space
|
||||
self.set_len(len + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue