#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
extern crate unreachable;
use unreachable::UncheckedOptionExt;
pub(crate) mod lib {
#[cfg(feature = "std")]
pub(crate) use std::*;
#[cfg(not(feature = "std"))]
pub(crate) use core::*;
}
use lib::borrow::{Borrow, BorrowMut};
use lib::{cmp, fmt, hash, iter, mem, ops, ptr, slice};
#[cfg(feature = "std")]
use lib::io;
trait PointerMethods {
unsafe fn padd(self, count: usize) -> Self;
}
impl<T> PointerMethods for *const T {
#[inline(always)]
unsafe fn padd(self, count: usize) -> Self {
#[cfg(has_pointer_methods)]
return self.add(count);
#[cfg(not(has_pointer_methods))]
return self.offset(count as isize);
}
}
impl<T> PointerMethods for *mut T {
#[inline(always)]
unsafe fn padd(self, count: usize) -> Self {
#[cfg(has_pointer_methods)]
return self.add(count);
#[cfg(not(has_pointer_methods))]
return self.offset(count as isize);
}
}
pub unsafe trait Array {
type Item;
fn size() -> usize;
fn ptr(&self) -> *const Self::Item;
fn ptr_mut(&mut self) -> *mut Self::Item;
}
macro_rules! impl_array(
($($size:expr),+) => {
$(
unsafe impl<T> Array for [T; $size] {
type Item = T;
fn size() -> usize { $size }
fn ptr(&self) -> *const T { self.as_ptr() }
fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() }
}
)+
}
);
impl_array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000 }
#[deprecated(note = "Use `Extend` and `Deref<[T]>` instead")]
pub trait VecLike<T>:
ops::Index<usize, Output=T> +
ops::IndexMut<usize> +
ops::Index<ops::Range<usize>, Output=[T]> +
ops::IndexMut<ops::Range<usize>> +
ops::Index<ops::RangeFrom<usize>, Output=[T]> +
ops::IndexMut<ops::RangeFrom<usize>> +
ops::Index<ops::RangeTo<usize>, Output=[T]> +
ops::IndexMut<ops::RangeTo<usize>> +
ops::Index<ops::RangeFull, Output=[T]> +
ops::IndexMut<ops::RangeFull> +
ops::DerefMut<Target = [T]> +
Extend<T> {
fn push(&mut self, value: T);
fn pop(&mut self) -> Option<T>;
}
#[allow(deprecated)]
impl<T> VecLike<T> for Vec<T> {
#[inline]
fn push(&mut self, value: T) {
Vec::push(self, value);
}
#[inline]
fn pop(&mut self) -> Option<T> {
Vec::pop(self)
}
}
pub trait ExtendFromSlice<T> {
fn extend_from_slice(&mut self, other: &[T]);
}
impl<T: Clone> ExtendFromSlice<T> for Vec<T> {
fn extend_from_slice(&mut self, other: &[T]) {
Vec::extend_from_slice(self, other)
}
}
pub struct Drain<'a, T: 'a> {
iter: slice::IterMut<'a, T>,
}
impl<'a, T: 'a> Iterator for Drain<'a,T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
self.iter.next().map(|reference| unsafe { ptr::read(reference) })
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
self.iter.next_back().map(|reference| unsafe { ptr::read(reference) })
}
}
impl<'a, T> ExactSizeIterator for Drain<'a, T> { }
impl<'a, T: 'a> Drop for Drain<'a,T> {
fn drop(&mut self) {
for _ in self.by_ref() {}
}
}
struct SetLenOnDrop<'a> {
len: &'a mut usize,
local_len: usize,
}
impl<'a> SetLenOnDrop<'a> {
#[inline]
fn new(len: &'a mut usize) -> Self {
SetLenOnDrop { local_len: *len, len: len }
}
#[inline]
fn increment_len(&mut self, increment: usize) {
self.local_len += increment;
}
}
impl<'a> Drop for SetLenOnDrop<'a> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
}
}
pub struct StackVec<A: Array> {
pub length: usize,
pub data: mem::ManuallyDrop<A>,
}
impl<A: Array> StackVec<A> {
#[inline]
pub fn new() -> StackVec<A> {
unsafe {
StackVec {
length: 0,
data: mem::uninitialized(),
}
}
}
#[inline]
pub fn from_vec(vec: Vec<A::Item>) -> StackVec<A> {
assert!(vec.len() <= A::size());
unsafe { Self::from_vec_unchecked(vec) }
}
pub unsafe fn from_vec_unchecked(mut vec: Vec<A::Item>) -> StackVec<A> {
let mut data: A = mem::uninitialized();
let len = vec.len();
vec.set_len(0);
ptr::copy_nonoverlapping(vec.as_ptr(), data.ptr_mut(), len);
StackVec {
length: len,
data: mem::ManuallyDrop::new(data),
}
}
#[inline]
pub fn from_buf(buf: A) -> StackVec<A> {
StackVec {
length: A::size(),
data: mem::ManuallyDrop::new(buf),
}
}
#[inline]
pub fn from_buf_and_len(buf: A, len: usize) -> StackVec<A> {
assert!(len <= A::size());
unsafe { StackVec::from_buf_and_len_unchecked(buf, len) }
}
#[inline]
pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> StackVec<A> {
StackVec {
length: len,
data: mem::ManuallyDrop::new(buf),
}
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
self.length = new_len;
}
#[inline]
pub fn len(&self) -> usize {
self.length
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn capacity(&self) -> usize {
A::size()
}
pub fn drain(&mut self) -> Drain<A::Item> {
unsafe {
let slice = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len());
self.set_len(0);
Drain {
iter: slice.iter_mut(),
}
}
}
#[inline]
pub fn push(&mut self, value: A::Item) {
assert!(self.len() < self.capacity());
unsafe {
ptr::write(self.as_mut_ptr().padd(self.length), value);
self.length += 1;
}
}
#[inline]
pub fn pop(&mut self) -> Option<A::Item> {
unsafe {
if self.len() == 0 {
None
} else {
self.length -=1;
Some(ptr::read(self.as_mut_ptr().padd(self.length)))
}
}
}
pub fn truncate(&mut self, len: usize) {
unsafe {
while len < self.length {
self.length -= 1;
ptr::drop_in_place(self.as_mut_ptr().padd(self.length));
}
}
}
#[inline]
pub fn as_slice(&self) -> &[A::Item] {
self
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [A::Item] {
self
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> A::Item {
let len = self.len();
self.swap(len - 1, index);
unsafe { self.pop().unchecked_unwrap() }
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0);
}
pub fn remove(&mut self, index: usize) -> A::Item {
assert!(index < self.len());
unsafe {
self.length -= 1;
let ptr = self.as_mut_ptr().padd(index);
let item = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, self.length - index);
item
}
}
pub fn insert(&mut self, index: usize, element: A::Item) {
assert!(index < self.len() && self.len() < self.capacity());
unsafe {
let ptr = self.as_mut_ptr().padd(index);
ptr::copy(ptr, ptr.offset(1), self.length - index);
ptr::write(ptr, element);
self.length += 1;
}
}
pub fn insert_many<I: iter::IntoIterator<Item=A::Item>>(&mut self, index: usize, iterable: I) {
let iter = iterable.into_iter();
if index == self.len() {
return self.extend(iter);
}
let (lower_size_bound, _) = iter.size_hint();
assert!(lower_size_bound <= std::isize::MAX as usize);
assert!(index + lower_size_bound >= index);
assert!(self.len() + lower_size_bound <= self.capacity());
unsafe {
let old_len = self.len();
assert!(index <= old_len);
let mut ptr = self.as_mut_ptr().padd(index);
ptr::copy(ptr, ptr.padd(lower_size_bound), old_len - index);
self.set_len(index);
let mut num_added = 0;
for element in iter {
let mut cur = ptr.padd(num_added);
if num_added >= lower_size_bound {
assert!(self.len() + 1 <= self.capacity());
ptr = self.as_mut_ptr().padd(index);
cur = ptr.padd(num_added);
ptr::copy(cur, cur.padd(1), old_len - index);
}
ptr::write(cur, element);
num_added += 1;
}
if num_added < lower_size_bound {
ptr::copy(ptr.padd(lower_size_bound), ptr.padd(num_added), old_len - index);
}
self.set_len(old_len + num_added);
}
}
pub fn into_vec(self) -> Vec<A::Item> {
self.into_iter().collect()
}
pub fn into_inner(self) -> Result<A, Self> {
if self.len() != A::size() {
Err(self)
} else {
unsafe {
let data = ptr::read(&self.data);
mem::forget(self);
Ok(mem::ManuallyDrop::into_inner(data))
}
}
}
pub fn retain<F: FnMut(&mut A::Item) -> bool>(&mut self, mut f: F) {
let mut del = 0;
let len = self.len();
for i in 0..len {
if !f(&mut self[i]) {
del += 1;
} else if del > 0 {
self.swap(i - del, i);
}
}
self.truncate(len - del);
}
pub fn dedup(&mut self) where A::Item: PartialEq<A::Item> {
self.dedup_by(|a, b| a == b);
}
pub fn dedup_by<F>(&mut self, mut same_bucket: F)
where F: FnMut(&mut A::Item, &mut A::Item) -> bool
{
let len = self.len();
if len <= 1 {
return;
}
let ptr = self.as_mut_ptr();
let mut w: usize = 1;
unsafe {
for r in 1..len {
let p_r = ptr.offset(r as isize);
let p_wm1 = ptr.offset((w - 1) as isize);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.offset(1);
mem::swap(&mut *p_r, &mut *p_w);
}
w += 1;
}
}
}
self.truncate(w);
}
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where F: FnMut(&mut A::Item) -> K,
K: PartialEq<K>
{
self.dedup_by(|a, b| key(a) == key(b));
}
}
impl<A: Array> StackVec<A> where A::Item: Copy {
pub fn from_slice(slice: &[A::Item]) -> Self {
assert!(slice.len() <= A::size());
StackVec {
length: slice.len(),
data: unsafe {
let mut data: A = mem::uninitialized();
ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), slice.len());
mem::ManuallyDrop::new(data)
}
}
}
pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) {
assert!(index <= self.len() && self.len() + slice.len() <= self.capacity());
unsafe {
let len = self.len();
let slice_ptr = slice.as_ptr();
let ptr = self.as_mut_ptr().padd(index);
ptr::copy(ptr, ptr.padd(slice.len()), len - index);
ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len());
self.set_len(len + slice.len());
}
}
#[inline]
pub fn extend_from_slice(&mut self, slice: &[A::Item]) {
let len = self.len();
self.insert_from_slice(len, slice);
}
}
impl<A: Array> StackVec<A> where A::Item: Clone {
pub fn resize(&mut self, len: usize, value: A::Item) {
assert!(len <= self.capacity());
let old_len = self.len();
if len > old_len {
self.extend(iter::repeat(value).take(len - old_len));
} else {
self.truncate(len);
}
}
pub fn from_elem(elem: A::Item, n: usize) -> Self {
assert!(n <= A::size());
let mut v = StackVec::<A>::new();
unsafe {
let ptr = v.as_mut_ptr();
let mut local_len = SetLenOnDrop::new(&mut v.length);
for i in 0..n as isize {
ptr::write(ptr.offset(i), elem.clone());
local_len.increment_len(1);
}
}
v
}
}
impl<A: Array> ops::Deref for StackVec<A> {
type Target = [A::Item];
#[inline]
fn deref(&self) -> &[A::Item] {
unsafe {
slice::from_raw_parts(self.data.ptr(), self.len())
}
}
}
impl<A: Array> ops::DerefMut for StackVec<A> {
#[inline]
fn deref_mut(&mut self) -> &mut [A::Item] {
unsafe {
slice::from_raw_parts_mut(self.data.ptr_mut(), self.len())
}
}
}
impl<A: Array> AsRef<[A::Item]> for StackVec<A> {
#[inline]
fn as_ref(&self) -> &[A::Item] {
self
}
}
impl<A: Array> AsMut<[A::Item]> for StackVec<A> {
#[inline]
fn as_mut(&mut self) -> &mut [A::Item] {
self
}
}
impl<A: Array> Borrow<[A::Item]> for StackVec<A> {
#[inline]
fn borrow(&self) -> &[A::Item] {
self
}
}
impl<A: Array> BorrowMut<[A::Item]> for StackVec<A> {
#[inline]
fn borrow_mut(&mut self) -> &mut [A::Item] {
self
}
}
#[cfg(feature = "std")]
impl<A: Array<Item = u8>> io::Write for StackVec<A> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.extend_from_slice(buf);
Ok(())
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<'a, A: Array> From<&'a [A::Item]> for StackVec<A> where A::Item: Clone {
#[inline]
fn from(slice: &'a [A::Item]) -> StackVec<A> {
slice.into_iter().cloned().collect()
}
}
impl<A: Array> From<Vec<A::Item>> for StackVec<A> {
#[inline]
fn from(vec: Vec<A::Item>) -> StackVec<A> {
StackVec::from_vec(vec)
}
}
impl<A: Array> From<A> for StackVec<A> {
#[inline]
fn from(array: A) -> StackVec<A> {
StackVec::from_buf(array)
}
}
macro_rules! impl_index {
($index_type: ty, $output_type: ty) => {
impl<A: Array> ops::Index<$index_type> for StackVec<A> {
type Output = $output_type;
#[inline]
fn index(&self, index: $index_type) -> &$output_type {
&(&**self)[index]
}
}
impl<A: Array> ops::IndexMut<$index_type> for StackVec<A> {
#[inline]
fn index_mut(&mut self, index: $index_type) -> &mut $output_type {
&mut (&mut **self)[index]
}
}
}
}
impl_index!(usize, A::Item);
impl_index!(ops::Range<usize>, [A::Item]);
impl_index!(ops::RangeFrom<usize>, [A::Item]);
impl_index!(ops::RangeFull, [A::Item]);
impl_index!(ops::RangeTo<usize>, [A::Item]);
#[cfg(has_range_inclusive)]
impl_index!(ops::RangeInclusive<usize>, [A::Item]);
#[cfg(has_range_inclusive)]
impl_index!(ops::RangeToInclusive<usize>, [A::Item]);
impl<A: Array> ExtendFromSlice<A::Item> for StackVec<A> where A::Item: Copy {
fn extend_from_slice(&mut self, other: &[A::Item]) {
StackVec::extend_from_slice(self, other)
}
}
#[allow(deprecated)]
impl<A: Array> VecLike<A::Item> for StackVec<A> {
#[inline]
fn push(&mut self, value: A::Item) {
StackVec::push(self, value);
}
#[inline]
fn pop(&mut self) -> Option<A::Item> {
StackVec::pop(self)
}
}
impl<A: Array> iter::FromIterator<A::Item> for StackVec<A> {
fn from_iter<I: iter::IntoIterator<Item=A::Item>>(iterable: I) -> StackVec<A> {
let mut v = StackVec::new();
v.extend(iterable);
v
}
}
impl<A: Array> Extend<A::Item> for StackVec<A> {
fn extend<I: iter::IntoIterator<Item=A::Item>>(&mut self, iterable: I) {
let mut iter = iterable.into_iter();
let (lower_bound, upper_bound) = iter.size_hint();
let upper_bound = upper_bound.expect("iterable must provide upper bound.");
assert!(self.len() + upper_bound <= self.capacity());
unsafe {
let len = self.len();
let ptr = self.as_mut_ptr().padd(len);
let mut count = 0;
while count < lower_bound {
if let Some(out) = iter.next() {
ptr::write(ptr.padd(count), out);
count += 1;
} else {
break;
}
}
self.set_len(len + count);
}
for elem in iter {
self.push(elem);
}
}
}
impl<A: Array> fmt::Debug for StackVec<A> where A::Item: fmt::Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<A: Array> Default for StackVec<A> {
#[inline]
fn default() -> StackVec<A> {
StackVec::new()
}
}
impl<A: Array> Drop for StackVec<A> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(&mut self[..]);
}
}
}
impl<A: Array> Clone for StackVec<A> where A::Item: Clone {
fn clone(&self) -> StackVec<A> {
let mut new_vector = StackVec::new();
for element in self.iter() {
new_vector.push(element.clone())
}
new_vector
}
}
impl<A: Array, B: Array> PartialEq<StackVec<B>> for StackVec<A>
where A::Item: PartialEq<B::Item>
{
#[inline]
fn eq(&self, other: &StackVec<B>) -> bool {
self[..] == other[..]
}
#[inline]
fn ne(&self, other: &StackVec<B>) -> bool {
self[..] != other[..]
}
}
impl<A: Array> Eq for StackVec<A> where A::Item: Eq {
}
impl<A: Array> PartialOrd for StackVec<A> where A::Item: PartialOrd {
#[inline]
fn partial_cmp(&self, other: &StackVec<A>) -> Option<cmp::Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<A: Array> Ord for StackVec<A> where A::Item: Ord {
#[inline]
fn cmp(&self, other: &StackVec<A>) -> cmp::Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<A: Array> hash::Hash for StackVec<A> where A::Item: hash::Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
unsafe impl<A: Array> Send for StackVec<A> where A::Item: Send {
}
pub struct IntoIter<A: Array> {
data: StackVec<A>,
current: usize,
end: usize,
}
impl<A: Array> Drop for IntoIter<A> {
fn drop(&mut self) {
for _ in self {
}
}
}
impl<A: Array> Iterator for IntoIter<A> {
type Item = A::Item;
#[inline]
fn next(&mut self) -> Option<A::Item> {
if self.current == self.end {
None
}
else {
unsafe {
let current = self.current;
self.current += 1;
Some(ptr::read(self.data.as_ptr().padd(current)))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.end - self.current;
(size, Some(size))
}
}
impl<A: Array> DoubleEndedIterator for IntoIter<A> {
#[inline]
fn next_back(&mut self) -> Option<A::Item> {
if self.current == self.end {
None
}
else {
unsafe {
self.end -= 1;
Some(ptr::read(self.data.as_ptr().padd(self.end)))
}
}
}
}
impl<A: Array> ExactSizeIterator for IntoIter<A> {
}
impl<A: Array> IntoIterator for StackVec<A> {
type IntoIter = IntoIter<A>;
type Item = A::Item;
fn into_iter(mut self) -> Self::IntoIter {
unsafe {
let len = self.len();
self.set_len(0);
IntoIter {
data: self,
current: 0,
end: len,
}
}
}
}
impl<'a, A: Array> IntoIterator for &'a StackVec<A> {
type IntoIter = slice::Iter<'a, A::Item>;
type Item = &'a A::Item;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, A: Array> IntoIterator for &'a mut StackVec<A> {
type IntoIter = slice::IterMut<'a, A::Item>;
type Item = &'a mut A::Item;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
#[macro_export]
macro_rules! stackvec {
(@one $x:expr) => (1usize);
($elem:expr; $n:expr) => ({
$crate::StackVec::from_elem($elem, $n)
});
($($x:expr),*$(,)*) => ({
#[allow(unused_mut)] {
let mut vec = $crate::StackVec::new();
$(vec.push($x);)*
vec
}
});
}
#[cfg(test)]
mod test {
use super::*;
use super::lib::iter::FromIterator;
use super::lib::rc::Rc;
#[test]
pub fn test_zero() {
let v = StackVec::<[usize; 0]>::new();
assert_eq!(v.len(), 0);
}
#[test]
#[should_panic]
pub fn test_panic() {
let mut v = StackVec::<[usize; 0]>::new();
v.push(0);
}
#[test]
pub fn test_inline() {
let mut v = StackVec::<[_; 16]>::new();
v.push("hello".to_owned());
v.push("there".to_owned());
assert_eq!(&*v, &[
"hello".to_owned(),
"there".to_owned(),
][..]);
}
#[test]
#[should_panic]
pub fn test_spill() {
let mut v = StackVec::<[_; 2]>::new();
v.push("hello".to_owned());
assert_eq!(v[0], "hello");
v.push("there".to_owned());
v.push("burma".to_owned());
assert_eq!(v[0], "hello");
v.push("shave".to_owned());
assert_eq!(&*v, &[
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
][..]);
}
#[test]
#[should_panic]
pub fn test_double_spill() {
let mut v = StackVec::<[_; 2]>::new();
v.push("hello".to_owned());
v.push("there".to_owned());
v.push("burma".to_owned());
v.push("shave".to_owned());
v.push("hello".to_owned());
v.push("there".to_owned());
v.push("burma".to_owned());
v.push("shave".to_owned());
assert_eq!(&*v, &[
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
"hello".to_owned(),
"there".to_owned(),
"burma".to_owned(),
"shave".to_owned(),
][..]);
}
#[test]
fn issue_4() {
StackVec::<[Box<u32>; 2]>::new();
}
#[test]
fn issue_5() {
assert!(Some(StackVec::<[&u32; 2]>::new()).is_some());
}
#[test]
fn drain_test() {
let mut v: StackVec<[u8; 2]> = StackVec::new();
v.push(3);
assert_eq!(v.drain().collect::<Vec<_>>(), &[3]);
}
#[test]
fn drain_rev_test() {
let mut v: StackVec<[u8; 2]> = StackVec::new();
v.push(3);
assert_eq!(v.drain().rev().collect::<Vec<_>>(), &[3]);
}
#[test]
fn into_iter() {
let mut v: StackVec<[u8; 2]> = StackVec::new();
v.push(3);
assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3]);
}
#[test]
fn into_iter_rev() {
let mut v: StackVec<[u8; 2]> = StackVec::new();
v.push(3);
assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[3]);
}
#[test]
fn into_iter_drop() {
use lib::cell::Cell;
struct DropCounter<'a>(&'a Cell<i32>);
impl<'a> Drop for DropCounter<'a> {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
}
}
{
let cell = Cell::new(0);
let mut v: StackVec<[DropCounter; 2]> = StackVec::new();
v.push(DropCounter(&cell));
v.into_iter();
assert_eq!(cell.get(), 1);
}
{
let cell = Cell::new(0);
let mut v: StackVec<[DropCounter; 2]> = StackVec::new();
v.push(DropCounter(&cell));
v.push(DropCounter(&cell));
assert!(v.into_iter().next().is_some());
assert_eq!(cell.get(), 2);
}
}
#[test]
fn test_capacity() {
let v: StackVec<[u8; 2]> = StackVec::new();
assert_eq!(v.capacity(), 2);
}
#[test]
fn test_truncate() {
let mut v: StackVec<[Box<u8>; 8]> = StackVec::new();
for x in 0..8 {
v.push(Box::new(x));
}
v.truncate(4);
assert_eq!(v.len(), 4);
assert_eq!(*v.swap_remove(1), 1);
assert_eq!(*v.remove(1), 3);
v.insert(1, Box::new(3));
assert_eq!(&v.iter().map(|v| **v).collect::<Vec<_>>(), &[0, 3, 2]);
}
#[test]
fn test_insert_many() {
let mut v: StackVec<[u8; 8]> = StackVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_many(1, [5, 6].iter().cloned());
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
}
#[test]
fn test_insert_from_slice() {
let mut v: StackVec<[u8; 8]> = StackVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.insert_from_slice(1, &[5, 6]);
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 5, 6, 1, 2, 3]);
}
#[test]
fn test_extend_from_slice() {
let mut v: StackVec<[u8; 8]> = StackVec::new();
for x in 0..4 {
v.push(x);
}
assert_eq!(v.len(), 4);
v.extend_from_slice(&[5, 6]);
assert_eq!(&v.iter().map(|v| *v).collect::<Vec<_>>(), &[0, 1, 2, 3, 5, 6]);
}
#[test]
#[should_panic]
fn test_drop_panic_smallvec() {
struct DropPanic;
impl Drop for DropPanic {
fn drop(&mut self) {
panic!("drop");
}
}
let mut v = StackVec::<[_; 1]>::new();
v.push(DropPanic);
}
#[test]
fn test_eq() {
let mut a: StackVec<[u32; 2]> = StackVec::new();
let mut b: StackVec<[u32; 2]> = StackVec::new();
let mut c: StackVec<[u32; 2]> = StackVec::new();
a.push(1);
a.push(2);
b.push(1);
b.push(2);
c.push(3);
c.push(4);
assert!(a == b);
assert!(a != c);
}
#[test]
fn test_ord() {
let mut a: StackVec<[u32; 2]> = StackVec::new();
let mut b: StackVec<[u32; 2]> = StackVec::new();
let mut c: StackVec<[u32; 2]> = StackVec::new();
a.push(1);
b.push(1);
b.push(1);
c.push(1);
c.push(2);
assert!(a < b);
assert!(b > a);
assert!(b < c);
assert!(c > b);
}
#[cfg(feature = "std")]
#[test]
fn test_hash() {
use std::hash::Hash;
use std::collections::hash_map::DefaultHasher;
{
let mut a: StackVec<[u32; 2]> = StackVec::new();
let b = [1, 2];
a.extend(b.iter().cloned());
let mut hasher = DefaultHasher::new();
assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
}
{
let mut a: StackVec<[u32; 4]> = StackVec::new();
let b = [1, 2, 11, 12];
a.extend(b.iter().cloned());
let mut hasher = DefaultHasher::new();
assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher));
}
}
#[test]
fn test_as_ref() {
let mut a: StackVec<[u32; 3]> = StackVec::new();
a.push(1);
assert_eq!(a.as_ref(), [1]);
a.push(2);
assert_eq!(a.as_ref(), [1, 2]);
a.push(3);
assert_eq!(a.as_ref(), [1, 2, 3]);
}
#[test]
fn test_as_mut() {
let mut a: StackVec<[u32; 3]> = StackVec::new();
a.push(1);
assert_eq!(a.as_mut(), [1]);
a.push(2);
assert_eq!(a.as_mut(), [1, 2]);
a.push(3);
assert_eq!(a.as_mut(), [1, 2, 3]);
a.as_mut()[1] = 4;
assert_eq!(a.as_mut(), [1, 4, 3]);
}
#[test]
fn test_borrow() {
use std::borrow::Borrow;
let mut a: StackVec<[u32; 3]> = StackVec::new();
a.push(1);
assert_eq!(a.borrow(), [1]);
a.push(2);
assert_eq!(a.borrow(), [1, 2]);
a.push(3);
assert_eq!(a.borrow(), [1, 2, 3]);
}
#[test]
fn test_borrow_mut() {
use std::borrow::BorrowMut;
let mut a: StackVec<[u32; 3]> = StackVec::new();
a.push(1);
assert_eq!(a.borrow_mut(), [1]);
a.push(2);
assert_eq!(a.borrow_mut(), [1, 2]);
a.push(3);
assert_eq!(a.borrow_mut(), [1, 2, 3]);
BorrowMut::<[u32]>::borrow_mut(&mut a)[1] = 4;
assert_eq!(a.borrow_mut(), [1, 4, 3]);
}
#[test]
fn test_from() {
assert_eq!(&StackVec::<[u32; 2]>::from(&[1][..])[..], [1]);
assert_eq!(&StackVec::<[u32; 3]>::from(&[1, 2, 3][..])[..], [1, 2, 3]);
let vec = vec![];
let stack_vec: StackVec<[u8; 3]> = StackVec::from(vec);
assert_eq!(&*stack_vec, &[]);
drop(stack_vec);
let vec = vec![1, 2, 3, 4, 5];
let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec);
assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]);
drop(stack_vec);
let vec = vec![1, 2, 3, 4, 5];
let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec);
assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]);
drop(stack_vec);
let array = [1];
let stack_vec: StackVec<[u8; 1]> = StackVec::from(array);
assert_eq!(&*stack_vec, &[1]);
drop(stack_vec);
let array = [99; 128];
let stack_vec: StackVec<[u8; 128]> = StackVec::from(array);
assert_eq!(&*stack_vec, vec![99u8; 128].as_slice());
drop(stack_vec);
}
#[test]
fn test_from_slice() {
assert_eq!(&StackVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]);
assert_eq!(&StackVec::<[u32; 3]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]);
}
#[test]
fn test_exact_size_iterator() {
let mut vec = StackVec::<[u32; 3]>::from(&[1, 2, 3][..]);
assert_eq!(vec.clone().into_iter().len(), 3);
assert_eq!(vec.drain().len(), 3);
}
#[test]
#[allow(deprecated)]
fn veclike_deref_slice() {
use super::VecLike;
fn test<T: VecLike<i32>>(vec: &mut T) {
assert!(!vec.is_empty());
assert_eq!(vec.len(), 3);
vec.sort();
assert_eq!(&vec[..], [1, 2, 3]);
}
let mut vec = StackVec::<[i32; 3]>::from(&[3, 1, 2][..]);
test(&mut vec);
}
#[test]
fn test_into_vec() {
let vec = StackVec::<[u8; 2]>::from_iter(0..2);
assert_eq!(vec.into_vec(), vec![0, 1]);
let vec = StackVec::<[u8; 3]>::from_iter(0..3);
assert_eq!(vec.into_vec(), vec![0, 1, 2]);
}
#[test]
fn test_into_inner() {
let vec = StackVec::<[u8; 2]>::from_iter(0..2);
assert_eq!(vec.into_inner(), Ok([0, 1]));
let vec = StackVec::<[u8; 2]>::from_iter(0..1);
assert_eq!(vec.clone().into_inner(), Err(vec));
let vec = StackVec::<[u8; 3]>::from_iter(0..3);
assert_eq!(vec.clone().into_inner(), Ok([0, 1, 2]));
let vec = StackVec::<[u8; 4]>::from_iter(0..3);
assert_eq!(vec.clone().into_inner(), Err(vec));
}
#[test]
fn test_from_vec() {
let vec = vec![];
let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec);
assert_eq!(&*stack_vec, &[]);
drop(stack_vec);
let vec = vec![];
let stack_vec: StackVec<[u8; 1]> = StackVec::from_vec(vec);
assert_eq!(&*stack_vec, &[]);
drop(stack_vec);
let vec = vec![1];
let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec);
assert_eq!(&*stack_vec, &[1]);
drop(stack_vec);
let vec = vec![1, 2, 3];
let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec);
assert_eq!(&*stack_vec, &[1, 2, 3]);
drop(stack_vec);
let vec = vec![1, 2, 3, 4, 5];
let stack_vec: StackVec<[u8; 5]> = StackVec::from_vec(vec);
assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]);
drop(stack_vec);
}
#[test]
fn test_retain() {
let mut sv: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 3, 4]);
sv.retain(|&mut i| i != 3);
assert_eq!(sv.pop(), Some(4));
assert_eq!(sv.pop(), Some(2));
assert_eq!(sv.pop(), Some(1));
assert_eq!(sv.pop(), None);
let one = Rc::new(1);
let mut sv: StackVec<[Rc<i32>; 3]> = StackVec::new();
sv.push(Rc::clone(&one));
assert_eq!(Rc::strong_count(&one), 2);
sv.retain(|_| false);
assert_eq!(Rc::strong_count(&one), 1);
}
#[test]
fn test_dedup() {
let mut dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 2, 3, 3]);
dupes.dedup();
assert_eq!(&*dupes, &[1, 2, 3]);
let mut empty: StackVec<[i32; 5]> = StackVec::new();
empty.dedup();
assert!(empty.is_empty());
let mut all_ones: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 1, 1, 1]);
all_ones.dedup();
assert_eq!(all_ones.len(), 1);
let mut no_dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 4, 5]);
no_dupes.dedup();
assert_eq!(no_dupes.len(), 5);
}
#[test]
fn test_resize() {
let mut v: StackVec<[i32; 8]> = StackVec::new();
v.push(1);
v.resize(5, 0);
assert_eq!(v[..], [1, 0, 0, 0, 0][..]);
v.resize(2, -1);
assert_eq!(v[..], [1, 0][..]);
}
#[cfg(feature = "std")]
#[test]
fn test_write() {
use io::Write;
let data = [1, 2, 3, 4, 5];
let mut small_vec: StackVec<[u8; 5]> = StackVec::new();
let len = small_vec.write(&data[..]).unwrap();
assert_eq!(len, 5);
assert_eq!(small_vec.as_ref(), data.as_ref());
let mut small_vec: StackVec<[u8; 5]> = StackVec::new();
small_vec.write_all(&data[..]).unwrap();
assert_eq!(small_vec.as_ref(), data.as_ref());
}
}