65 lines
2.3 KiB
Rust
65 lines
2.3 KiB
Rust
use core::cmp;
|
|
use core::iter::TrustedLen;
|
|
use core::ptr;
|
|
|
|
use crate::raw_vec::RawVec;
|
|
|
|
use super::{SpecExtend, Vec};
|
|
|
|
/// Another specialization trait for Vec::from_iter
|
|
/// necessary to manually prioritize overlapping specializations
|
|
/// see [`SpecFromIter`](super::SpecFromIter) for details.
|
|
pub(super) trait SpecFromIterNested<T, I> {
|
|
fn from_iter(iter: I) -> Self;
|
|
}
|
|
|
|
impl<T, I> SpecFromIterNested<T, I> for Vec<T>
|
|
where
|
|
I: Iterator<Item = T>,
|
|
{
|
|
default fn from_iter(mut iterator: I) -> Self {
|
|
// Unroll the first iteration, as the vector is going to be
|
|
// expanded on this iteration in every case when the iterable is not
|
|
// empty, but the loop in extend_desugared() is not going to see the
|
|
// vector being full in the few subsequent loop iterations.
|
|
// So we get better branch prediction.
|
|
let mut vector = match iterator.next() {
|
|
None => return Vec::new(),
|
|
Some(element) => {
|
|
let (lower, _) = iterator.size_hint();
|
|
let initial_capacity =
|
|
cmp::max(RawVec::<T>::MIN_NON_ZERO_CAP, lower.saturating_add(1));
|
|
let mut vector = Vec::with_capacity(initial_capacity);
|
|
unsafe {
|
|
// SAFETY: We requested capacity at least 1
|
|
ptr::write(vector.as_mut_ptr(), element);
|
|
vector.set_len(1);
|
|
}
|
|
vector
|
|
}
|
|
};
|
|
// must delegate to spec_extend() since extend() itself delegates
|
|
// to spec_from for empty Vecs
|
|
<Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
|
|
vector
|
|
}
|
|
}
|
|
|
|
impl<T, I> SpecFromIterNested<T, I> for Vec<T>
|
|
where
|
|
I: TrustedLen<Item = T>,
|
|
{
|
|
fn from_iter(iterator: I) -> Self {
|
|
let mut vector = match iterator.size_hint() {
|
|
(_, Some(upper)) => Vec::with_capacity(upper),
|
|
// TrustedLen contract guarantees that `size_hint() == (_, None)` means that there
|
|
// are more than `usize::MAX` elements.
|
|
// Since the previous branch would eagerly panic if the capacity is too large
|
|
// (via `with_capacity`) we do the same here.
|
|
_ => panic!("capacity overflow"),
|
|
};
|
|
// reuse extend specialization for TrustedLen
|
|
vector.spec_extend(iterator);
|
|
vector
|
|
}
|
|
}
|