| 1 | use core::iter::TrustedLen; |
| 2 | use core::{cmp, ptr}; |
| 3 | |
| 4 | use super::{SpecExtend, Vec}; |
| 5 | use crate::raw_vec::RawVec; |
| 6 | |
| 7 | /// Another specialization trait for Vec::from_iter |
| 8 | /// necessary to manually prioritize overlapping specializations |
| 9 | /// see [`SpecFromIter`](super::SpecFromIter) for details. |
| 10 | pub(super) trait SpecFromIterNested<T, I> { |
| 11 | fn from_iter(iter: I) -> Self; |
| 12 | } |
| 13 | |
| 14 | impl<T, I> SpecFromIterNested<T, I> for Vec<T> |
| 15 | where |
| 16 | I: Iterator<Item = T>, |
| 17 | { |
| 18 | #[track_caller ] |
| 19 | default fn from_iter(mut iterator: I) -> Self { |
| 20 | // Unroll the first iteration, as the vector is going to be |
| 21 | // expanded on this iteration in every case when the iterable is not |
| 22 | // empty, but the loop in extend_desugared() is not going to see the |
| 23 | // vector being full in the few subsequent loop iterations. |
| 24 | // So we get better branch prediction. |
| 25 | let mut vector = match iterator.next() { |
| 26 | None => return Vec::new(), |
| 27 | Some(element) => { |
| 28 | let (lower, _) = iterator.size_hint(); |
| 29 | let initial_capacity = |
| 30 | cmp::max(RawVec::<T>::MIN_NON_ZERO_CAP, lower.saturating_add(1)); |
| 31 | let mut vector = Vec::with_capacity(initial_capacity); |
| 32 | unsafe { |
| 33 | // SAFETY: We requested capacity at least 1 |
| 34 | ptr::write(vector.as_mut_ptr(), element); |
| 35 | vector.set_len(1); |
| 36 | } |
| 37 | vector |
| 38 | } |
| 39 | }; |
| 40 | // must delegate to spec_extend() since extend() itself delegates |
| 41 | // to spec_from for empty Vecs |
| 42 | <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator); |
| 43 | vector |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | impl<T, I> SpecFromIterNested<T, I> for Vec<T> |
| 48 | where |
| 49 | I: TrustedLen<Item = T>, |
| 50 | { |
| 51 | #[track_caller ] |
| 52 | fn from_iter(iterator: I) -> Self { |
| 53 | let mut vector: Vec = match iterator.size_hint() { |
| 54 | (_, Some(upper: usize)) => Vec::with_capacity(upper), |
| 55 | // TrustedLen contract guarantees that `size_hint() == (_, None)` means that there |
| 56 | // are more than `usize::MAX` elements. |
| 57 | // Since the previous branch would eagerly panic if the capacity is too large |
| 58 | // (via `with_capacity`) we do the same here. |
| 59 | _ => panic!("capacity overflow" ), |
| 60 | }; |
| 61 | // reuse extend specialization for TrustedLen |
| 62 | vector.spec_extend(iter:iterator); |
| 63 | vector |
| 64 | } |
| 65 | } |
| 66 | |