use traits::*;
use qindex_multi::MultiIndexable;
use raw_vec::RawVec;
use core::array::FixedSizeArray;
use rustc_serialize::{self, Encodable, Decodable};
use std::borrow::{Borrow, BorrowMut};
use std::fmt::{self, Debug};
use std::hash::{self, Hash};
use std::iter::FromIterator;
use std::ops::{Deref, DerefMut, Index, IndexMut};
use std::{cmp, slice, mem, ptr};
enum SmallVecData<T, A>
where A: FixedSizeArray<T>,
{
Inline(A),
Heap(RawVec<T>),
}
#[unsafe_no_drop_flag]
pub struct SmallVec<T, A>
where A: FixedSizeArray<T>,
{
len: usize,
data: SmallVecData<T, A>,
}
impl<T, A> SmallVec<T, A>
where A: FixedSizeArray<T>,
{
pub fn inline_capacity() -> usize {
mem::size_of::<A>() / mem::size_of::<T>()
}
pub fn from_fixed(array: A) -> Self {
SmallVec{
len: Self::inline_capacity(),
data: SmallVecData::Inline(array),
}
}
pub fn into_fixed(self) -> A {
assert!(!self.spilled());
assert!(self.len() == self.capacity());
let ret = unsafe { ptr::read(self.as_ptr() as *const A) };
mem::forget(self);
ret
}
pub fn new() -> Self {
let mut ret = Self::from_fixed(unsafe { mem::uninitialized() });
ret.len = 0;
ret
}
pub fn with_capacity(cap: usize) -> Self {
let mut ret = Self::new();
if cap > Self::inline_capacity() {
ret.reserve(cap);
}
ret
}
pub fn spilled(&self) -> bool {
match self.data {
SmallVecData::Inline(_) => false,
SmallVecData::Heap(_) => true,
}
}
pub unsafe fn set_len(&mut self, len: usize){ self.len = len; }
pub fn len(&self) -> usize { self.len }
#[inline]
pub fn as_slice(&self) -> &[T] {
match &self.data {
&SmallVecData::Inline(ref array) => unsafe {
slice::from_raw_parts(array as *const A as *const T, self.len)
},
&SmallVecData::Heap(ref raw_vec) => unsafe {
slice::from_raw_parts(raw_vec.ptr(), self.len)
},
}
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
match &mut self.data {
&mut SmallVecData::Inline(ref mut array) => unsafe {
slice::from_raw_parts_mut(array as *const A as *mut T, self.len)
},
&mut SmallVecData::Heap(ref raw_vec) => unsafe {
slice::from_raw_parts_mut(raw_vec.ptr() as *mut _, self.len)
},
}
}
pub fn as_ptr(&self) -> *const T { self.as_slice().as_ptr() }
pub fn as_mut_ptr(&mut self) -> *mut T { self.as_mut_slice().as_mut_ptr() }
pub fn capacity(&self) -> usize {
if mem::size_of::<T>() == 0 { return !0; }
match self.data {
SmallVecData::Inline(_) => Self::inline_capacity(),
SmallVecData::Heap(ref raw_vec) => raw_vec.cap(),
}
}
pub fn reserve(&mut self, additional: usize){
if mem::size_of::<T>() == 0 { return }
if !self.spilled() {
let old_ptr = self.as_mut_ptr();
let raw_vec: RawVec<T> = RawVec::with_capacity(self.len + additional);
unsafe {
ptr::copy_nonoverlapping(old_ptr, raw_vec.ptr() as *mut _, self.len);
ptr::write(&mut self.data, SmallVecData::Heap(raw_vec));
}
} else {
match &mut self.data {
&mut SmallVecData::Heap(ref mut raw_vec) => {
raw_vec.reserve(self.len, additional);
}
_ => unreachable!(),
}
}
}
pub fn insert(&mut self, idx: usize, val: T){
let len = self.len;
assert!(idx <= len);
if idx == self.capacity() { self.reserve(1) }
unsafe {
let ptr = self.as_mut_ptr().offset(idx as isize);
ptr::copy(ptr, ptr.offset(1), len - idx);
ptr::write(ptr, val);
}
self.len += 1;
}
pub fn remove(&mut self, idx: usize) -> T {
let len = self.len;
assert!(idx < len);
unsafe {
let ptr = self.as_mut_ptr().offset(idx as isize);
let ret = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, len - idx - 1);
self.len -= 1;
ret
}
}
pub fn clear(&mut self) {
for idx in 0..self.len {
unsafe { ptr::read(self.as_ptr().offset(idx as isize)); }
}
self.len = 0;
}
fn needs_drop(&self) -> bool {
self.len != mem::POST_DROP_USIZE
}
}
impl<T, A> Drop for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn drop(&mut self){
if self.needs_drop() {
self.clear();
if !self.spilled() {
unsafe { ptr::write(&mut self.data, SmallVecData::Heap(RawVec::new())); }
}
}
}
}
impl<T, A> ImmutableCollection for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn len(&self) -> usize { (*self).len() }
}
impl<T, A> MutableCollection for SmallVec<T, A>
where A: FixedSizeArray<T>,
{}
impl<T, A> GrowableCollection for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn capacity(&self) -> usize { (*self).capacity() }
fn reserve(&mut self, additional: usize){ (*self).reserve(additional) }
fn reserve_exact(&mut self, additional: usize){ (*self).reserve(additional) }
fn clear(&mut self){ (*self).clear(); }
}
impl<'a, T, A> ImmutableSequenceTypes<'a, T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type Iter = slice::Iter<'a, T>;
}
impl<T, A> ImmutableSequence<T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn get<'a>(&'a self, idx: usize) -> Option<<Self as ImmutableSequenceTypes<'a, T>>::Output> { self.as_slice().get(idx) }
fn iter<'a>(&'a self) -> <Self as ImmutableSequenceTypes<'a, T>>::Iter { self.as_slice().iter() }
}
impl<'a, T, A> MutableSequenceTypes<'a, T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type IterMut = slice::IterMut<'a, T>;
}
impl<T, A> MutableSequence<T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn get_mut<'a>(&'a mut self, idx: usize) -> Option<&mut T>
where Self: ImmutableSequenceTypes<'a, T, Output = &'a T>
{
self.as_mut_slice().get_mut(idx)
}
fn iter_mut<'a>(&'a mut self) -> <Self as MutableSequenceTypes<'a, T>>::IterMut
where Self: ImmutableSequenceTypes<'a, T, Output = &'a T>
{
self.as_mut_slice().iter_mut()
}
fn swap(&mut self, a: usize, b: usize){
self.as_mut_slice().swap(a, b);
}
fn sort_by<F>(&mut self, compare: F)
where F: FnMut(&T, &T) -> cmp::Ordering
{
self.as_mut_slice().sort_by(compare);
}
}
impl<T, A> GrowableSequence<T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn insert(&mut self, idx: usize, val: T){ (*self).insert(idx, val); }
fn remove(&mut self, idx: usize) -> T { (*self).remove(idx) }
}
impl<T, A> SmallVec<T, A>
where A: FixedSizeArray<T>,
{
pub fn push(&mut self, val: T){ GrowableSequence::push(self, val); }
pub fn pop(&mut self) -> Option<T> { GrowableSequence::pop(self) }
}
impl<T, A> FromIterator<T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn from_iter<I>(iterable: I) -> Self
where I: IntoIterator<Item = T>
{
let iter = iterable.into_iter();
let mut ret = SmallVec::new();
Extend::extend(&mut ret, iter);
ret
}
}
impl<T, A> Extend<T> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn extend<I>(&mut self, iterable: I)
where I: IntoIterator<Item = T>
{
extend_sequence(self, iterable)
}
}
impl<'a, T, A> IntoIterator for &'a SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}
impl<'a, T, A> IntoIterator for &'a mut SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}
impl<T, A> Index<usize> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type Output = T;
fn index(&self, idx: usize) -> &Self::Output { &self.as_slice()[idx] }
}
impl<T, A> IndexMut<usize> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn index_mut(&mut self, idx: usize) -> &mut Self::Output { &mut self.as_mut_slice()[idx] }
}
unsafe impl<T, A> MultiIndexable<usize> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{}
impl<T, A> Clone for SmallVec<T, A>
where A: FixedSizeArray<T>, T: Clone,
{
fn clone(&self) -> Self {
SmallVec::from_iter(self.as_slice().iter().cloned())
}
fn clone_from(&mut self, src: &Self){
self.clear();
Extend::extend(self, src.iter().cloned());
}
}
impl<T, A> Default for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn default() -> Self { Self::new() }
}
impl<T, A> Deref for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
type Target = [T];
fn deref(&self) -> &Self::Target { self.as_slice() }
}
impl<T, A> DerefMut for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() }
}
impl<Rhs, T, A> PartialEq<Rhs> for SmallVec<T, A>
where Rhs: Borrow<[T]>, T: PartialEq, A: FixedSizeArray<T>,
{
fn eq(&self, other: &Rhs) -> bool { self.as_slice() == other.borrow() }
}
impl<T, A> Eq for SmallVec<T, A>
where T: Eq, A: FixedSizeArray<T>,
{}
impl<Rhs, T, A> PartialOrd<Rhs> for SmallVec<T, A>
where Rhs: Borrow<[T]>, T: PartialOrd, A: FixedSizeArray<T>,
{
fn partial_cmp(&self, other: &Rhs) -> Option<cmp::Ordering> {
self.as_slice().partial_cmp(other.borrow())
}
}
impl<T, A> Ord for SmallVec<T, A>
where T: Ord, A: FixedSizeArray<T>,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T, A> Borrow<[T]> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn borrow(&self) -> &[T] { self.as_slice() }
}
impl<T, A> BorrowMut<[T]> for SmallVec<T, A>
where A: FixedSizeArray<T>,
{
fn borrow_mut(&mut self) -> &mut [T] { self.as_mut_slice() }
}
impl<'a, T, A> From<&'a [T]> for SmallVec<T, A>
where T: Clone, A: FixedSizeArray<T>,
{
fn from(src: &'a [T]) -> Self {
Self::from_iter(src.iter().cloned())
}
}
impl<T, A> Hash for SmallVec<T, A>
where T: Hash, A: FixedSizeArray<T>,
{
fn hash<H>(&self, state: &mut H)
where H: hash::Hasher
{
self.as_slice().hash(state)
}
}
impl<T, A> Debug for SmallVec<T, A>
where T: Debug, A: FixedSizeArray<T>,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.as_slice().fmt(formatter)
}
}
impl<T, A> Encodable for SmallVec<T, A>
where T: Encodable, A: FixedSizeArray<T>,
{
fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
where E: rustc_serialize::Encoder
{
self.as_slice().encode(e)
}
}
impl<T, A> Decodable for SmallVec<T, A>
where T: Decodable, A: FixedSizeArray<T>,
{
fn decode<D>(d: &mut D) -> Result<Self, D::Error>
where D: rustc_serialize::Decoder
{
d.read_seq(|d, len| {
let mut v = Self::with_capacity(len);
for i in 0..len {
v.push(try!(d.read_seq_elt(i, |d| T::decode(d))));
}
Ok(v)
})
}
}
#[test]
fn push_n_spill_n_pop(){
let mut v = SmallVec::<u8, [u8; 2]>::new();
v.push(1);
v.push(2);
assert!(!v.spilled());
v.push(3);
assert!(v.spilled());
v.push(4);
assert_eq!(v.pop().unwrap(), 4);
assert_eq!(v.pop().unwrap(), 3);
assert_eq!(v.pop().unwrap(), 2);
assert_eq!(v.pop().unwrap(), 1);
assert!(v.spilled());
}
#[test]
fn clone(){
let mut v = SmallVec::<u8, [u8; 4]>::new();
Extend::extend(&mut v, vec![1, 2, 3, 4, 5]);
let cloned = v.clone();
assert_eq!(cloned.len(), 5);
assert!(cloned.spilled());
v.pop();
let cloned = v.clone();
assert_eq!(cloned.len(), 4);
assert!(!cloned.spilled());
}