use crate::alloc::Allocator; use core::iter::TrustedLen; use core::ptr::{self}; use core::slice::{self}; use super::{IntoIter, SetLenOnDrop, Vec}; // Specialization trait used for Vec::extend pub(super) trait SpecExtend { fn spec_extend(&mut self, iter: I); } impl SpecExtend for Vec where I: Iterator, { default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter) } } impl SpecExtend for Vec where I: TrustedLen, { default 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) ); } if let Some(additional) = high { self.reserve(additional); unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); let mut local_len = SetLenOnDrop::new(&mut self.len); iterator.for_each(move |element| { ptr::write(ptr, element); ptr = ptr.offset(1); // NB can't overflow since we would have had to alloc the address space local_len.increment_len(1); }); } } else { self.extend_desugared(iterator) } } } impl SpecExtend> for Vec { fn spec_extend(&mut self, mut iterator: IntoIter) { unsafe { self.append_elements(iterator.as_slice() as _); } iterator.ptr = iterator.end; } } impl<'a, T: 'a, I, A: Allocator + 'a> SpecExtend<&'a T, I> for Vec where I: Iterator, T: Clone, { default fn spec_extend(&mut self, iterator: I) { self.spec_extend(iterator.cloned()) } } impl<'a, T: 'a, A: Allocator + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec where T: Copy, { fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); unsafe { self.append_elements(slice) }; } }