#![cfg_attr(not(feature = "std"), no_std)]
#![allow(unused_unsafe)]
#![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))]
extern crate alloc;
use alloc::borrow::{Borrow, BorrowMut};
use alloc::vec::Vec;
use core::{cmp, fmt, hash, iter, mem, ops, ptr, slice};
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,
}
}
#[inline]
unsafe fn increment_len(&mut self, n: usize) {
self.local_len += n;
}
#[inline]
unsafe fn decrement_len(&mut self, n: usize) {
self.local_len -= n;
}
}
impl<'a> Drop for SetLenOnDrop<'a> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
}
}
struct DropOnPanic<T> {
start: *mut T,
skip: ops::Range<usize>,
len: usize,
}
impl<T> Drop for DropOnPanic<T> {
fn drop(&mut self) {
for i in 0..self.len {
if !self.skip.contains(&i) {
unsafe {
ptr::drop_in_place(self.start.add(i));
}
}
}
}
}
pub struct StackVec<T, const N: usize> {
data: [mem::MaybeUninit<T>; N],
length: usize,
}
impl<T, const N: usize> StackVec<T, N> {
#[inline]
pub fn new() -> StackVec<T, N> {
StackVec {
length: 0,
data: unsafe { mem::MaybeUninit::uninit().assume_init() },
}
}
#[inline]
pub fn from_vec(vec: Vec<T>) -> StackVec<T, N> {
assert!(vec.len() <= N);
unsafe { Self::from_vec_unchecked(vec) }
}
#[allow(deprecated)]
pub unsafe fn from_vec_unchecked(vec: Vec<T>) -> StackVec<T, N> {
debug_assert!(vec.len() <= N);
let mut v: StackVec<T, N> = Self::new();
let len = vec.len();
for (index, item) in vec.into_iter().enumerate() {
v.data[index].write(item);
}
v.length = len;
v
}
#[inline]
pub fn from_buf(buf: [T; N]) -> StackVec<T, N> {
let len = buf.len();
unsafe { StackVec::from_buf_and_len_unchecked(buf, len) }
}
#[inline]
pub fn from_buf_and_len(buf: [T; N], len: usize) -> StackVec<T, N> {
assert!(len <= N && len <= buf.len());
unsafe { StackVec::from_buf_and_len_unchecked(buf, len) }
}
#[inline]
pub unsafe fn from_buf_and_len_unchecked(buf: [T; N], len: usize) -> StackVec<T, N> {
debug_assert!(len <= N && len <= buf.len());
let mut v = Self::new();
{
let mut local_len = SetLenOnDrop::new(&mut v.length);
for (index, item) in buf.into_iter().take(len).enumerate() {
v.data[index].write(item);
unsafe { local_len.increment_len(1) };
}
}
v
}
#[inline]
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= N);
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 {
N
}
pub fn drain(&mut self) -> Drain<'_, T> {
unsafe {
let slice = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len());
self.length = 0;
Drain {
iter: slice.iter_mut(),
}
}
}
#[inline]
pub fn push(&mut self, value: T) {
assert!(self.len() < self.capacity());
unsafe {
let len = self.len();
self.data[len].write(value);
self.set_len(len + 1);
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
let len = self.len();
if len == 0 {
None
} else {
unsafe {
self.set_len(len - 1);
let init = self.as_ptr().add(self.len());
Some(ptr::read(init))
}
}
}
pub fn truncate(&mut self, len: usize) {
unsafe {
while len < self.len() {
self.set_len(self.len() - 1);
self.data[self.len()].assume_init_drop();
}
}
}
fn as_ptr(&self) -> *const T {
self.data.as_ptr() as *const T
}
fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr() as *mut T
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
let len = self.len();
self.swap(len - 1, index);
unsafe { self.pop().unwrap_unchecked() }
}
#[inline]
pub fn clear(&mut self) {
self.truncate(0);
}
pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len());
unsafe {
self.length -= 1;
let ptr = self.as_mut_ptr().add(index);
let item = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, self.length - index);
item
}
}
pub fn insert(&mut self, index: usize, element: T) {
assert!(index < self.len() && self.len() < self.capacity());
unsafe {
let ptr = self.as_mut_ptr().add(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 = T>>(&mut self, index: usize, iterable: I) {
let mut iter = iterable.into_iter();
if index == self.len() {
return self.extend(iter);
}
let (lower_bound, _) = iter.size_hint();
assert!(lower_bound <= isize::MAX as usize); assert!(index + lower_bound >= index); assert!(self.len() + lower_bound <= self.capacity());
let mut num_added = 0;
let old_len = self.len();
assert!(index <= old_len);
unsafe {
let start = self.as_mut_ptr();
let ptr = start.add(index);
ptr::copy(ptr, ptr.add(lower_bound), old_len - index);
self.length = 0;
let mut guard = DropOnPanic {
start,
skip: index..(index + lower_bound),
len: old_len + lower_bound,
};
while num_added < lower_bound {
let element = match iter.next() {
Some(x) => x,
None => break,
};
let cur = ptr.add(num_added);
ptr::write(cur, element);
guard.skip.start += 1;
num_added += 1;
}
if num_added < lower_bound {
ptr::copy(ptr.add(lower_bound), ptr.add(num_added), old_len - index);
}
self.set_len(old_len + num_added);
mem::forget(guard);
for element in iter {
self.insert(index + num_added, element);
num_added += 1;
}
}
}
pub fn into_vec(self) -> Vec<T> {
self.into_iter().collect()
}
pub fn into_inner(self) -> Result<[T; N], Self> {
if self.len() != N {
Err(self)
} else {
unsafe {
let this = mem::ManuallyDrop::new(self);
let array = ptr::read(this.as_ptr() as *const [T; N]);
Ok(array)
}
}
}
pub fn retain<F: FnMut(&mut T) -> 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
T: PartialEq<T>,
{
self.dedup_by(|a, b| a == b);
}
pub fn dedup_by<F>(&mut self, mut same_bucket: F)
where
F: FnMut(&mut T, &mut T) -> bool,
{
let len = self.len();
assert!(len <= self.data.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.add(r);
let p_wm1 = ptr.add(w - 1);
if !same_bucket(&mut *p_r, &mut *p_wm1) {
if r != w {
let p_w = p_wm1.offset(1);
ptr::swap(p_r, p_w);
}
w += 1;
}
}
}
self.truncate(w);
}
pub fn dedup_by_key<F, K>(&mut self, mut key: F)
where
F: FnMut(&mut T) -> K,
K: PartialEq<K>,
{
self.dedup_by(|a, b| key(a) == key(b));
}
}
impl<T, const N: usize> StackVec<T, N>
where
T: Copy,
{
pub fn from_slice(slice: &[T]) -> Self {
assert!(slice.len() <= N);
let mut v = StackVec::new();
unsafe {
let mut local_len = SetLenOnDrop::new(&mut v.length);
for (index, item) in slice.iter().enumerate() {
v.data[index].write(*item);
local_len.increment_len(1);
}
}
v
}
pub fn insert_from_slice(&mut self, index: usize, slice: &[T]) {
assert!(index <= self.len() && self.len() + slice.len() <= self.capacity());
let len = self.len();
let ptr = unsafe { self.as_mut_ptr().add(index) };
unsafe { ptr::copy(ptr, ptr.add(slice.len()), len - index) };
let mut local_len = SetLenOnDrop::new(&mut self.length);
for (i, item) in slice.iter().enumerate() {
self.data[index + i].write(*item);
unsafe { local_len.increment_len(1) };
}
}
#[inline]
pub fn extend_from_slice(&mut self, slice: &[T]) {
assert!(self.len() + slice.len() <= self.capacity());
let len = self.len();
let mut local_len = SetLenOnDrop::new(&mut self.length);
for (i, item) in slice.iter().enumerate() {
self.data[len + i].write(*item);
unsafe { local_len.increment_len(1) };
}
}
}
impl<T, const N: usize> StackVec<T, N>
where
T: Clone,
{
pub fn resize(&mut self, len: usize, value: T) {
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: T, n: usize) -> Self {
assert!(n <= N);
let mut v = StackVec::<T, N>::new();
{
let mut local_len = SetLenOnDrop::new(&mut v.length);
for i in 0..n {
v.data[i].write(elem.clone());
unsafe { local_len.increment_len(1) };
}
}
v
}
}
impl<T, const N: usize> ops::Deref for StackVec<T, N> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe {
let ptr = self.as_ptr();
slice::from_raw_parts(ptr, self.len())
}
}
}
impl<T, const N: usize> ops::DerefMut for StackVec<T, N> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe {
let ptr = self.as_mut_ptr();
slice::from_raw_parts_mut(ptr, self.len())
}
}
}
impl<T, const N: usize> AsRef<[T]> for StackVec<T, N> {
#[inline]
fn as_ref(&self) -> &[T] {
self
}
}
impl<T, const N: usize> AsMut<[T]> for StackVec<T, N> {
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self
}
}
impl<T, const N: usize> Borrow<[T]> for StackVec<T, N> {
#[inline]
fn borrow(&self) -> &[T] {
self
}
}
impl<T, const N: usize> BorrowMut<[T]> for StackVec<T, N> {
#[inline]
fn borrow_mut(&mut self) -> &mut [T] {
self
}
}
#[cfg(feature = "std")]
impl<const N: usize> ::std::io::Write for StackVec<u8, N> {
#[inline]
fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
self.extend_from_slice(buf);
Ok(buf.len())
}
#[inline]
fn write_all(&mut self, buf: &[u8]) -> ::std::io::Result<()> {
self.extend_from_slice(buf);
Ok(())
}
#[inline]
fn flush(&mut self) -> ::std::io::Result<()> {
Ok(())
}
}
impl<'a, T, const N: usize> From<&'a [T]> for StackVec<T, N>
where
T: Clone,
{
#[inline]
fn from(slice: &'a [T]) -> StackVec<T, N> {
slice.iter().cloned().collect()
}
}
impl<T, const N: usize> From<Vec<T>> for StackVec<T, N> {
#[inline]
fn from(vec: Vec<T>) -> StackVec<T, N> {
StackVec::from_vec(vec)
}
}
impl<T, const N: usize> From<[T; N]> for StackVec<T, N> {
#[inline]
fn from(array: [T; N]) -> StackVec<T, N> {
StackVec::from_buf(array)
}
}
macro_rules! impl_index {
($index_type: ty, $output_type: ty) => {
impl<T, const N: usize> ops::Index<$index_type> for StackVec<T, N> {
type Output = $output_type;
#[inline]
fn index(&self, index: $index_type) -> &$output_type {
&self.as_slice()[index]
}
}
impl<T, const N: usize> ops::IndexMut<$index_type> for StackVec<T, N> {
#[inline]
fn index_mut(&mut self, index: $index_type) -> &mut $output_type {
&mut self.as_mut_slice()[index]
}
}
};
}
impl_index!(usize, T);
impl_index!(ops::Range<usize>, [T]);
impl_index!(ops::RangeFrom<usize>, [T]);
impl_index!(ops::RangeFull, [T]);
impl_index!(ops::RangeTo<usize>, [T]);
impl_index!(ops::RangeInclusive<usize>, [T]);
impl_index!(ops::RangeToInclusive<usize>, [T]);
impl<T, const N: usize> ExtendFromSlice<T> for StackVec<T, N>
where
T: Copy,
{
fn extend_from_slice(&mut self, other: &[T]) {
StackVec::extend_from_slice(self, other)
}
}
impl<T, const N: usize> VecLike<T> for StackVec<T, N> {
#[inline]
fn push(&mut self, value: T) {
StackVec::push(self, value);
}
#[inline]
fn pop(&mut self) -> Option<T> {
StackVec::pop(self)
}
}
impl<T, const N: usize> iter::FromIterator<T> for StackVec<T, N> {
fn from_iter<I: iter::IntoIterator<Item = T>>(iterable: I) -> StackVec<T, N> {
let mut v = StackVec::new();
v.extend(iterable);
v
}
}
impl<T, const N: usize> Extend<T> for StackVec<T, N> {
fn extend<I: iter::IntoIterator<Item = T>>(&mut self, iterable: I) {
for elem in iterable.into_iter() {
self.push(elem);
}
}
}
impl<T, const N: usize> fmt::Debug for StackVec<T, N>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T, const N: usize> Default for StackVec<T, N> {
#[inline]
fn default() -> StackVec<T, N> {
StackVec::new()
}
}
impl<T, const N: usize> Drop for StackVec<T, N> {
fn drop(&mut self) {
unsafe {
let len = self.len();
let mut local_len = SetLenOnDrop::new(&mut self.length);
for item in &mut self.data[..len] {
item.assume_init_drop();
local_len.decrement_len(1);
}
}
}
}
impl<T, const N: usize> Clone for StackVec<T, N>
where
T: Clone,
{
fn clone(&self) -> StackVec<T, N> {
let mut v = StackVec::new();
for element in self.iter() {
v.push(element.clone())
}
v
}
}
impl<T, U, const TN: usize, const UN: usize> PartialEq<StackVec<U, UN>> for StackVec<T, TN>
where
T: PartialEq<U>,
{
#[inline]
fn eq(&self, other: &StackVec<U, UN>) -> bool {
self[..] == other[..]
}
}
impl<T, const N: usize> Eq for StackVec<T, N> where T: Eq {}
impl<T, const N: usize> PartialOrd for StackVec<T, N>
where
T: PartialOrd,
{
#[inline]
fn partial_cmp(&self, other: &StackVec<T, N>) -> Option<cmp::Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
}
impl<T, const N: usize> Ord for StackVec<T, N>
where
T: Ord,
{
#[inline]
fn cmp(&self, other: &StackVec<T, N>) -> cmp::Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T, const N: usize> hash::Hash for StackVec<T, N>
where
T: hash::Hash,
{
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state)
}
}
unsafe impl<T, const N: usize> Send for StackVec<T, N> where T: Send {}
pub struct IntoIter<T, const N: usize> {
data: StackVec<T, N>,
current: usize,
end: usize,
}
impl<T, const N: usize> Drop for IntoIter<T, N> {
fn drop(&mut self) {
for _ in self {}
}
}
impl<T, const N: usize> Iterator for IntoIter<T, N> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.current == self.end {
None
} else {
unsafe {
let current = self.current;
self.current += 1;
Some(ptr::read(self.data.as_ptr().add(current)))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.end - self.current;
(size, Some(size))
}
}
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
#[inline]
fn next_back(&mut self) -> Option<T> {
if self.current == self.end {
None
} else {
unsafe {
self.end -= 1;
Some(ptr::read(self.data.as_ptr().add(self.end)))
}
}
}
}
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
impl<T, const N: usize> IntoIterator for StackVec<T, N> {
type IntoIter = IntoIter<T, N>;
type Item = T;
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, T, const N: usize> IntoIterator for &'a StackVec<T, N> {
type IntoIter = slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, const N: usize> IntoIterator for &'a mut StackVec<T, N> {
type IntoIter = slice::IterMut<'a, T>;
type Item = &'a mut T;
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 alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::vec;
use core::iter::FromIterator;
struct BadBoundsIterator1(u8);
impl BadBoundsIterator1 {
pub fn new() -> Self {
BadBoundsIterator1(0)
}
}
impl Iterator for BadBoundsIterator1 {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
self.0 += 1;
if self.0 >= 10 {
None
} else {
Some(0x41)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let lower_bound = 20;
let upper_bound = Some(0);
(lower_bound, upper_bound)
}
}
struct BadBoundsIterator2(u8);
impl BadBoundsIterator2 {
pub fn new() -> Self {
BadBoundsIterator2(0)
}
}
impl Iterator for BadBoundsIterator2 {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
self.0 += 1;
if self.0 >= 30 {
None
} else {
Some(0x41)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let lower_bound = 0;
let upper_bound = Some(0);
(lower_bound, upper_bound)
}
}
struct BadSizeHint(u8);
impl BadSizeHint {
pub fn new(start: u8) -> Self {
BadSizeHint(start)
}
}
impl Iterator for BadSizeHint {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
self.0 += 1;
if self.0 >= 30 {
None
} else {
Some(0x41)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let lower_bound = 0;
let upper_bound = None;
(lower_bound, upper_bound)
}
}
#[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::<String, 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::<String, 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::<String, 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 core::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_many_buggy_iterator() {
let mut v: StackVec<u8, 64> = StackVec::new();
for x in 0..4 {
v.push(x);
}
v.insert_many(1, BadBoundsIterator1::new());
assert_eq!(
&v.iter().map(|v| *v).collect::<Vec<_>>(),
&[0, 65, 65, 65, 65, 65, 65, 65, 65, 65, 1, 2, 3]
);
let mut v: StackVec<u8, 64> = StackVec::new();
for x in 0..4 {
v.push(x);
}
v.insert_many(1, BadBoundsIterator2::new());
assert_eq!(v.len(), 33);
let mut v: StackVec<u8, 64> = StackVec::new();
for x in 0..4 {
v.push(x);
}
v.insert_many(1, BadSizeHint::new(1));
assert_eq!(v.len(), 32);
}
#[should_panic]
#[test]
fn test_insert_many_panic_buggy_iterator() {
let mut v: StackVec<u8, 8> = StackVec::new();
for x in 0..4 {
v.push(x);
}
v.insert_many(1, BadBoundsIterator2::new());
}
#[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::<DropPanic, 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::collections::hash_map::DefaultHasher;
use std::hash::Hash;
{
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 core::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 core::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]
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 std::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());
}
}