use std::{mem, iter, slice, vec};
use super::TwoSidedVec;
pub trait TwoSidedExtend<T> {
fn extend_back<I: IntoIterator<Item=T>>(&mut self, iter: I);
fn extend_front<I: IntoIterator<Item=T>>(&mut self, iter: I);
}
impl<T> TwoSidedExtend<T> for TwoSidedVec<T> {
#[inline]
fn extend_back<I: IntoIterator<Item=T>>(&mut self, iter: I) {
SpecExtend::<T, I::IntoIter>::extend_back(self, iter.into_iter())
}
#[inline]
fn extend_front<I: IntoIterator<Item=T>>(&mut self, iter: I) {
SpecExtend::<T, I::IntoIter>::extend_front(self, iter.into_iter())
}
}
impl<'a, T: Copy + 'a> TwoSidedExtend<&'a T> for TwoSidedVec<T> {
#[inline]
fn extend_back<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
SpecExtend::<&'a T, I::IntoIter>::extend_back(self, iter.into_iter())
}
#[inline]
fn extend_front<I: IntoIterator<Item=&'a T>>(&mut self, iter: I) {
SpecExtend::<&'a T, I::IntoIter>::extend_front(self, iter.into_iter())
}
}
trait SpecExtend<T, I> {
fn extend_back(&mut self, iter: I);
fn extend_front(&mut self, iter: I);
}
impl<T, I: Iterator<Item=T>> SpecExtend<T, I> for TwoSidedVec<T> {
#[inline]
default fn extend_back(&mut self, iter: I) {
self.default_extend_back(iter)
}
#[inline]
default fn extend_front(&mut self, iter: I) {
self.default_extend_front(iter)
}
}
impl<T, I: iter::TrustedLen<Item=T>> SpecExtend<T, I> for TwoSidedVec<T> {
default fn extend_back(&mut self, iter: I) {
let (low, high) = iter.size_hint();
if let Some(additional) = high {
debug_assert_eq!(additional, low);
self.reserve_back(additional);
debug_assert!(additional <= isize::max_value() as usize);
let mut ptr = self.start_ptr();
for value in iter {
unsafe {
ptr = ptr.sub(1);
ptr.write(value);
self.start_index -= 1;
}
}
} else {
self.default_extend_back(iter);
}
}
default fn extend_front(&mut self, iter: I) {
let (low, high) = iter.size_hint();
if let Some(additional) = high {
debug_assert_eq!(additional, low);
self.reserve_front(additional);
debug_assert!(additional <= isize::max_value() as usize);
let mut ptr = self.end_ptr();
for value in iter {
unsafe {
ptr.write(value);
ptr = ptr.add(1);
}
self.end_index += 1;
}
} else {
self.default_extend_front(iter);
}
}
}
impl<T> SpecExtend<T, vec::IntoIter<T>> for TwoSidedVec<T> {
#[inline]
fn extend_back(&mut self, iter: vec::IntoIter<T>) {
let elements = iter.collect::<Vec<T>>();
unsafe { self.raw_extend_back(elements.as_ptr(), elements.len()); }
mem::forget(elements);
}
#[inline]
fn extend_front(&mut self, iter: vec::IntoIter<T>) {
let elements = iter.collect::<Vec<T>>();
unsafe { self.raw_extend_front(elements.as_ptr(), elements.len()); }
mem::forget(elements);
}
}
impl<'a, T: Copy + 'a, I: Iterator<Item=&'a T>> SpecExtend<&'a T, I> for TwoSidedVec<T> {
#[inline]
default fn extend_back(&mut self, iter: I) {
TwoSidedExtend::extend_back(self, iter.cloned())
}
#[inline]
default fn extend_front(&mut self, iter: I) {
TwoSidedExtend::extend_front(self, iter.cloned());
}
}
impl<'a, T: Copy + 'a> SpecExtend<&'a T, slice::Iter<'a, T>> for TwoSidedVec<T> {
#[inline]
fn extend_back(&mut self, iter: slice::Iter<'a, T>) {
let target = iter.as_slice();
unsafe {
self.raw_extend_back(target.as_ptr(), target.len());
}
}
#[inline]
fn extend_front(&mut self, iter: slice::Iter<'a, T>) {
let target = iter.as_slice();
unsafe {
self.raw_extend_front(target.as_ptr(), target.len());
}
}
}