use super::LimitedSizeVec;
use super::storage::CompactStorage;
use serde::{Deserialize, Serialize};
use std::any::TypeId;
use std::hash::Hash;
const INLINE_CAPACITY: usize = 7;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CompactVec<T: CompactStorage> {
Inline([T::InlineType; INLINE_CAPACITY], u8),
Heap(LimitedSizeVec<T>),
}
impl<T: CompactStorage> CompactVec<T> {
#[inline]
pub fn new() -> Self {
CompactVec::Inline([T::InlineType::default(); INLINE_CAPACITY], 0)
}
#[inline]
fn transition_to_heap(&mut self) -> &mut LimitedSizeVec<T> {
match self {
CompactVec::Inline(storage, length) => {
let mut heap_vec = LimitedSizeVec::new();
for i in 0..*length {
heap_vec.push(T::from_inline(storage[i as usize]));
}
*self = CompactVec::Heap(heap_vec);
match self {
CompactVec::Heap(vec) => vec,
_ => unreachable!(),
}
}
CompactVec::Heap(vec) => vec,
}
}
#[inline]
pub fn push_unchecked(&mut self, value: T) {
debug_assert!(
T::CONVERSION_INFALLIBLE,
"push_unchecked only valid for infallible types"
);
match self {
CompactVec::Inline(storage, length) => {
if (*length as usize) < INLINE_CAPACITY {
storage[*length as usize] = T::to_inline_unchecked(value);
*length += 1;
} else {
self.transition_to_heap().push(value);
}
}
CompactVec::Heap(vec) => {
vec.push(value);
}
}
}
#[inline]
pub fn push(&mut self, value: T) {
if T::CONVERSION_INFALLIBLE {
self.push_unchecked(value);
return;
}
match self {
CompactVec::Inline(storage, length) => {
if (*length as usize) < INLINE_CAPACITY {
match T::to_inline(value) {
Ok(inline_value) => {
storage[*length as usize] = inline_value;
*length += 1;
}
Err(original_value) => {
self.transition_to_heap().push(original_value);
}
}
} else {
self.transition_to_heap().push(value);
}
}
CompactVec::Heap(vec) => {
vec.push(value);
}
}
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
match self {
CompactVec::Inline(storage, length) => {
if *length > 0 {
*length -= 1;
Some(T::from_inline(storage[*length as usize]))
} else {
None
}
}
CompactVec::Heap(vec) => vec.pop(),
}
}
#[inline]
pub fn len(&self) -> usize {
match self {
CompactVec::Inline(_, length) => *length as usize,
CompactVec::Heap(vec) => vec.len(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn get(&self, index: usize) -> Option<T> {
match self {
CompactVec::Inline(storage, length) => {
if index < *length as usize {
Some(T::from_inline(storage[index]))
} else {
None
}
}
CompactVec::Heap(vec) => vec.get(index).copied(),
}
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> T {
unsafe {
match self {
CompactVec::Inline(storage, _) => T::from_inline(*storage.get_unchecked(index)),
CompactVec::Heap(vec) => *vec.get_unchecked(index),
}
}
}
#[inline]
pub fn is_inline(&self) -> bool {
matches!(self, CompactVec::Inline(_, _))
}
#[inline]
pub fn capacity(&self) -> usize {
match self {
CompactVec::Inline(_, _) => INLINE_CAPACITY,
CompactVec::Heap(vec) => vec.capacity(),
}
}
#[inline]
pub fn as_slice(&self) -> &[T] {
if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
match self {
CompactVec::Inline(storage, length) => {
unsafe {
let ptr = storage.as_ptr() as *const T;
std::slice::from_raw_parts(ptr, *length as usize)
}
}
CompactVec::Heap(vec) => vec.as_slice(),
}
} else {
panic!(
"Cannot get slice from inline storage for non-zero-cost types - use iter() instead"
)
}
}
#[inline]
pub fn remove(&mut self, index: usize) -> T {
if index >= self.len() {
panic!(
"removal index (is {}) should be < len (is {})",
index,
self.len()
);
}
match self {
CompactVec::Inline(storage, length) => {
let result = T::from_inline(storage[index]);
for i in index..(*length as usize - 1) {
storage[i] = storage[i + 1];
}
*length -= 1;
result
}
CompactVec::Heap(vec) => vec.remove(index),
}
}
#[inline]
pub fn insert(&mut self, index: usize, element: T) {
if index > self.len() {
panic!(
"insertion index (is {}) should be <= len (is {})",
index,
self.len()
);
}
match self {
CompactVec::Inline(storage, length) => {
if (*length as usize) >= INLINE_CAPACITY || T::to_inline(element).is_err() {
self.transition_to_heap().insert(index, element);
} else {
for i in (index..*length as usize).rev() {
storage[i + 1] = storage[i];
}
storage[index] = T::to_inline(element).unwrap_or_else(|_| unreachable!());
*length += 1;
}
}
CompactVec::Heap(vec) => vec.insert(index, element),
}
}
#[inline]
pub fn truncate(&mut self, len: usize) {
match self {
CompactVec::Inline(_, length) => {
if len < *length as usize {
*length = len as u8;
}
}
CompactVec::Heap(vec) => vec.truncate(len),
}
}
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
let current_len = self.len();
if new_len > current_len {
for _ in current_len..new_len {
self.push(value);
}
} else {
self.truncate(new_len);
}
}
#[inline]
pub fn extend_from_slice(&mut self, other: &[T]) {
for item in other {
self.push(*item);
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
match self {
CompactVec::Inline(_, _) => {
let new_capacity = self.len() + additional;
if self.capacity() >= new_capacity {
return;
}
if new_capacity > INLINE_CAPACITY {
self.transition_to_heap().reserve(additional);
}
}
CompactVec::Heap(vec) => vec.reserve(additional),
}
}
#[inline]
pub fn clear(&mut self) {
match self {
CompactVec::Inline(_, length) => *length = 0,
CompactVec::Heap(vec) => vec.clear(),
}
}
#[inline]
pub fn contains(&self, value: &T) -> bool
where
T: PartialEq,
{
match self {
CompactVec::Inline(storage, length) => {
for i in 0..*length as usize {
if T::from_inline(storage[i]) == *value {
return true;
}
}
false
}
CompactVec::Heap(vec) => vec.contains(value),
}
}
#[inline]
pub fn sort(&mut self)
where
T: Ord,
{
match self {
CompactVec::Inline(storage, length) => {
if *length <= 1 {
return;
}
for i in 1..*length {
let mut j = i as usize;
while j > 0 && T::from_inline(storage[j - 1]) > T::from_inline(storage[j]) {
storage.swap(j - 1, j);
j -= 1;
}
}
}
CompactVec::Heap(vec) => vec.sort(),
}
}
#[inline]
pub fn take(&mut self) -> Self {
std::mem::take(self)
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
match self {
CompactVec::Inline(storage, length) => {
if index < *length as usize {
if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
unsafe {
let ptr = storage.as_mut_ptr() as *mut T;
Some(&mut *ptr.add(index))
}
} else {
self.transition_to_heap().get_mut(index)
}
} else {
None
}
}
CompactVec::Heap(vec) => vec.get_mut(index),
}
}
#[inline]
pub unsafe fn get_mut_unchecked(&mut self, index: usize) -> &mut T {
unsafe {
match self {
CompactVec::Inline(storage, _) => {
if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
let ptr = storage.as_mut_ptr() as *mut T;
&mut *ptr.add(index)
} else {
self.transition_to_heap().get_mut_unchecked(index)
}
}
CompactVec::Heap(vec) => vec.get_mut_unchecked(index),
}
}
}
#[inline]
pub fn as_slice_mut(&mut self) -> &mut [T] {
match self {
CompactVec::Inline(storage, length) => {
if TypeId::of::<T>() == TypeId::of::<T::InlineType>() {
unsafe {
let ptr = storage.as_mut_ptr() as *mut T;
std::slice::from_raw_parts_mut(ptr, *length as usize)
}
} else {
self.transition_to_heap().as_mut()
}
}
CompactVec::Heap(vec) => vec.as_mut(),
}
}
#[inline]
pub fn iter(&self) -> CompactVecIter<'_, T> {
match self {
CompactVec::Inline(storage, length) => CompactVecIter::Inline(storage, 0, *length),
CompactVec::Heap(vec) => CompactVecIter::Heap(vec.iter()),
}
}
}
impl<T: CompactStorage> Default for CompactVec<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub enum CompactVecIter<'a, T: CompactStorage> {
Inline(&'a [T::InlineType; INLINE_CAPACITY], u8, u8),
Heap(std::slice::Iter<'a, T>),
}
impl<'a, T: CompactStorage> Iterator for CompactVecIter<'a, T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
CompactVecIter::Inline(storage, index, length) => {
if *index < *length {
let result = T::from_inline(storage[*index as usize]);
*index += 1;
Some(result)
} else {
None
}
}
CompactVecIter::Heap(iter) => iter.next().copied(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
CompactVecIter::Inline(_, index, length) => {
let remaining = (*length - *index) as usize;
(remaining, Some(remaining))
}
CompactVecIter::Heap(iter) => iter.size_hint(),
}
}
}
impl<'a, T: CompactStorage> ExactSizeIterator for CompactVecIter<'a, T> {}
impl<T> AsMut<[T]> for CompactVec<T>
where
T: CompactStorage,
{
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
impl<T> From<Vec<T>> for CompactVec<T>
where
T: CompactStorage,
{
#[inline]
fn from(vec: Vec<T>) -> Self {
if vec.len() > INLINE_CAPACITY {
Self::Heap(LimitedSizeVec::from(vec))
} else {
let mut compact_vec = Self::new();
for item in vec {
compact_vec.push(item);
}
compact_vec
}
}
}
impl<T, const N: usize> From<[T; N]> for CompactVec<T>
where
T: CompactStorage,
{
#[inline]
fn from(array: [T; N]) -> Self {
let mut compact_vec = Self::new();
for item in array {
compact_vec.push(item);
}
compact_vec
}
}
impl<T, const N: usize> From<&[T; N]> for CompactVec<T>
where
T: CompactStorage,
{
#[inline]
fn from(array: &[T; N]) -> Self {
let mut compact_vec = Self::new();
for item in array {
compact_vec.push(*item);
}
compact_vec
}
}
impl<T> From<&[T]> for CompactVec<T>
where
T: CompactStorage + Clone,
{
#[inline]
fn from(slice: &[T]) -> Self {
let mut compact_vec = Self::new();
for item in slice {
compact_vec.push(*item);
}
compact_vec
}
}
impl<T> From<&Vec<T>> for CompactVec<T>
where
T: CompactStorage + Clone,
{
#[inline]
fn from(vec: &Vec<T>) -> Self {
Self::from(vec.as_slice())
}
}
impl<T> From<CompactVec<T>> for Vec<T>
where
T: CompactStorage,
{
#[inline]
fn from(compact_vec: CompactVec<T>) -> Self {
match compact_vec {
CompactVec::Inline(storage, length) => {
let mut vec = Vec::with_capacity(length as usize);
for i in 0..length {
vec.push(T::from_inline(storage[i as usize]));
}
vec
}
CompactVec::Heap(vec) => vec.into(),
}
}
}
impl<T: CompactStorage + Hash> Hash for CompactVec<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for item in self.iter() {
item.hash(state);
}
}
}
impl<T: CompactStorage + PartialEq> PartialEq for CompactVec<T> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
self.iter().zip(other.iter()).all(|(a, b)| a == b)
}
}
impl<T: CompactStorage + Eq> Eq for CompactVec<T> {}
pub enum CompactVecIntoIter<T: CompactStorage> {
Inline([T::InlineType; INLINE_CAPACITY], u8, u8),
Heap(<LimitedSizeVec<T> as IntoIterator>::IntoIter),
}
impl<T: CompactStorage> Iterator for CompactVecIntoIter<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
CompactVecIntoIter::Inline(storage, index, length) => {
if *index < *length {
let result = T::from_inline(storage[*index as usize]);
*index += 1;
Some(result)
} else {
None
}
}
CompactVecIntoIter::Heap(iter) => iter.next(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
CompactVecIntoIter::Inline(_, index, length) => {
let remaining = (*length - *index) as usize;
(remaining, Some(remaining))
}
CompactVecIntoIter::Heap(iter) => iter.size_hint(),
}
}
}
impl<T: CompactStorage> ExactSizeIterator for CompactVecIntoIter<T> {}
impl<T: CompactStorage> FromIterator<T> for CompactVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let iter = iter.into_iter();
let (min_len, max_len) = iter.size_hint();
if let Some(len) = max_len {
if len <= INLINE_CAPACITY {
if T::CONVERSION_INFALLIBLE {
let mut storage = [T::InlineType::default(); INLINE_CAPACITY];
let mut i = 0;
for next in iter {
storage[i] = T::to_inline_unchecked(next);
i += 1;
}
return CompactVec::Inline(storage, i as u8);
}
} else {
return CompactVec::Heap(iter.collect::<LimitedSizeVec<T>>());
}
} else {
if min_len > INLINE_CAPACITY {
return CompactVec::Heap(iter.collect::<LimitedSizeVec<T>>());
}
}
let mut compact_vec = Self::new();
for item in iter {
compact_vec.push(item);
}
compact_vec
}
}
impl<T> IntoIterator for CompactVec<T>
where
T: CompactStorage,
{
type Item = T;
type IntoIter = CompactVecIntoIter<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
match self {
CompactVec::Inline(storage, length) => CompactVecIntoIter::Inline(storage, 0, length),
CompactVec::Heap(vec) => CompactVecIntoIter::Heap(vec.into_iter()),
}
}
}
impl<'a, T> IntoIterator for &'a CompactVec<T>
where
T: CompactStorage,
{
type Item = T;
type IntoIter = CompactVecIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut CompactVec<T>
where
T: CompactStorage,
{
type Item = &'a mut T;
type IntoIter = std::slice::IterMut<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.as_slice_mut().iter_mut()
}
}
impl std::ops::Deref for CompactVec<i8> {
type Target = [i8];
#[inline]
fn deref(&self) -> &Self::Target {
match self {
CompactVec::Inline(storage, length) => unsafe {
std::slice::from_raw_parts(storage.as_ptr(), *length as usize)
},
CompactVec::Heap(vec) => vec.as_slice(),
}
}
}
impl std::ops::Deref for CompactVec<u8> {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
match self {
CompactVec::Inline(storage, length) => unsafe {
std::slice::from_raw_parts(storage.as_ptr(), *length as usize)
},
CompactVec::Heap(vec) => vec.as_slice(),
}
}
}
impl std::ops::Index<usize> for CompactVec<i8> {
type Output = i8;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match self {
CompactVec::Inline(storage, length) => {
if index >= *length as usize {
panic!(
"index out of bounds: the len is {} but the index is {}",
*length, index
);
}
&storage[index]
}
CompactVec::Heap(vec) => &vec[index],
}
}
}
impl std::ops::Index<usize> for CompactVec<u8> {
type Output = u8;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
match self {
CompactVec::Inline(storage, length) => {
if index >= *length as usize {
panic!(
"index out of bounds: the len is {} but the index is {}",
*length, index
);
}
&storage[index]
}
CompactVec::Heap(vec) => &vec[index],
}
}
}
impl AsRef<[i8]> for CompactVec<i8> {
#[inline]
fn as_ref(&self) -> &[i8] {
self.as_slice()
}
}
impl AsRef<[u8]> for CompactVec<u8> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_vec_with_elements<T: CompactStorage + Clone>(elements: &[T]) -> CompactVec<T> {
let mut vec: CompactVec<T> = CompactVec::new();
for elem in elements {
vec.push(*elem);
}
vec
}
#[test]
fn test_new() {
let vec: CompactVec<i8> = CompactVec::new();
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
assert!(vec.is_inline());
assert_eq!(vec.capacity(), INLINE_CAPACITY);
}
#[test]
fn test_default() {
let vec: CompactVec<i8> = CompactVec::default();
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
assert!(vec.is_inline());
}
#[test]
fn test_push_inline() {
let mut vec: CompactVec<i8> = CompactVec::new();
for i in 0..INLINE_CAPACITY as i8 {
vec.push(i);
assert_eq!(vec.len(), (i + 1) as usize);
assert!(vec.is_inline());
assert_eq!(vec.get(i as usize), Some(i));
}
assert_eq!(vec.len(), INLINE_CAPACITY);
assert!(vec.is_inline());
}
#[test]
fn test_push_transition_to_heap() {
let mut vec: CompactVec<i8> = CompactVec::new();
for i in 0..INLINE_CAPACITY as i8 {
vec.push(i);
}
assert!(vec.is_inline());
vec.push(INLINE_CAPACITY as i8);
assert!(!vec.is_inline());
assert_eq!(vec.len(), INLINE_CAPACITY + 1);
assert!(vec.capacity() > INLINE_CAPACITY);
for i in 0..=INLINE_CAPACITY as i8 {
assert_eq!(vec.get(i as usize), Some(i));
}
}
#[test]
fn test_push_unchecked() {
let mut vec: CompactVec<i8> = CompactVec::new();
vec.push_unchecked(42);
vec.push_unchecked(-10);
assert_eq!(vec.len(), 2);
assert_eq!(vec.get(0), Some(42));
assert_eq!(vec.get(1), Some(-10));
}
#[test]
fn test_pop() {
let mut vec: CompactVec<i8> = CompactVec::new();
assert_eq!(vec.pop(), None);
vec.push(1);
vec.push(2);
vec.push(3);
assert_eq!(vec.pop(), Some(3));
assert_eq!(vec.len(), 2);
assert_eq!(vec.pop(), Some(2));
assert_eq!(vec.pop(), Some(1));
assert_eq!(vec.len(), 0);
assert_eq!(vec.pop(), None);
}
#[test]
fn test_get_and_bounds() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
assert_eq!(vec.get(0), Some(1));
assert_eq!(vec.get(1), Some(2));
assert_eq!(vec.get(2), Some(3));
assert_eq!(vec.get(3), None);
assert_eq!(vec.get(100), None);
}
#[test]
fn test_get_unchecked() {
let vec = test_vec_with_elements(&[42i8, -10, 100]);
unsafe {
assert_eq!(vec.get_unchecked(0), 42);
assert_eq!(vec.get_unchecked(1), -10);
assert_eq!(vec.get_unchecked(2), 100);
}
}
#[test]
fn test_capacity() {
let mut vec: CompactVec<i8> = CompactVec::new();
assert_eq!(vec.capacity(), INLINE_CAPACITY);
for i in 0..INLINE_CAPACITY as i8 {
vec.push(i);
}
assert_eq!(vec.capacity(), INLINE_CAPACITY);
vec.push(INLINE_CAPACITY as i8);
assert!(vec.capacity() > INLINE_CAPACITY);
}
#[test]
fn test_remove() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
assert_eq!(vec.remove(2), 3);
assert_eq!(vec.len(), 4);
assert_eq!(vec.get(2), Some(4));
assert_eq!(vec.remove(0), 1);
assert_eq!(vec.len(), 3);
assert_eq!(vec.get(0), Some(2));
assert_eq!(vec.remove(2), 5);
assert_eq!(vec.len(), 2);
}
#[test]
#[should_panic(expected = "removal index")]
fn test_remove_out_of_bounds() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
vec.remove(3);
}
#[test]
fn test_insert() {
let mut vec = test_vec_with_elements(&[1i8, 3, 4]);
vec.insert(1, 2);
assert_eq!(vec.len(), 4);
assert_eq!(vec.get(0), Some(1));
assert_eq!(vec.get(1), Some(2));
assert_eq!(vec.get(2), Some(3));
assert_eq!(vec.get(3), Some(4));
vec.insert(0, 0);
assert_eq!(vec.len(), 5);
assert_eq!(vec.get(0), Some(0));
vec.insert(5, 5);
assert_eq!(vec.len(), 6);
assert_eq!(vec.get(5), Some(5));
}
#[test]
#[should_panic(expected = "insertion index")]
fn test_insert_out_of_bounds() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
vec.insert(4, 42);
}
#[test]
fn test_truncate() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
vec.truncate(3);
assert_eq!(vec.len(), 3);
assert_eq!(vec.get(2), Some(3));
assert_eq!(vec.get(3), None);
vec.truncate(10);
assert_eq!(vec.len(), 3);
vec.truncate(0);
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
}
#[test]
fn test_resize() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
vec.resize(5, 42);
assert_eq!(vec.len(), 5);
assert_eq!(vec.get(3), Some(42));
assert_eq!(vec.get(4), Some(42));
vec.resize(2, 99);
assert_eq!(vec.len(), 2);
assert_eq!(vec.get(1), Some(2));
assert_eq!(vec.get(2), None);
}
#[test]
fn test_extend_from_slice() {
let mut vec = test_vec_with_elements(&[1i8, 2]);
vec.extend_from_slice(&[3, 4, 5]);
assert_eq!(vec.len(), 5);
assert_eq!(vec.get(2), Some(3));
assert_eq!(vec.get(3), Some(4));
assert_eq!(vec.get(4), Some(5));
vec.extend_from_slice(&[6, 7, 8]);
assert_eq!(vec.len(), 8);
assert!(!vec.is_inline());
}
#[test]
fn test_reserve() {
let mut vec: CompactVec<i8> = CompactVec::new();
vec.reserve(5);
assert!(vec.is_inline());
vec.reserve(10);
assert!(!vec.is_inline());
assert!(vec.capacity() >= 10);
}
#[test]
fn test_clear() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
let was_inline = vec.is_inline();
vec.clear();
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
assert_eq!(vec.is_inline(), was_inline); }
#[test]
fn test_contains_method() {
let mut vec: CompactVec<i8> = CompactVec::new();
vec.push(1);
vec.push(2);
vec.push(3);
assert!(vec.contains(&1));
assert!(vec.contains(&2));
assert!(vec.contains(&3));
assert!(!vec.contains(&4));
assert!(!vec.contains(&0));
}
#[test]
fn test_sort() {
let mut vec = test_vec_with_elements(&[3i8, 1, 4, 1, 5]);
vec.sort();
assert_eq!(vec.get(0), Some(1));
assert_eq!(vec.get(1), Some(1));
assert_eq!(vec.get(2), Some(3));
assert_eq!(vec.get(3), Some(4));
assert_eq!(vec.get(4), Some(5));
}
#[test]
fn test_take() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
let taken = vec.take();
assert_eq!(taken.len(), 3);
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
assert!(vec.is_inline());
}
#[test]
fn test_as_slice_i8() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let slice = vec.as_slice();
assert_eq!(slice, &[1, 2, 3]);
}
#[test]
fn test_get_mut_i8() {
let mut vec = test_vec_with_elements(&[10i8, 20, 30]);
if let Some(elem) = vec.get_mut(1) {
*elem = 25;
}
assert_eq!(vec.get(1), Some(25));
}
#[test]
fn test_get_mut_unchecked_i8() {
let mut vec = test_vec_with_elements(&[42i8]);
unsafe {
*vec.get_mut_unchecked(0) = 100;
}
assert_eq!(vec.get(0), Some(100));
}
#[test]
fn test_as_slice_mut_i8() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
let slice = vec.as_slice_mut();
slice[1] = 10;
assert_eq!(vec.get(1), Some(10));
}
#[test]
fn test_iter() {
let vec = test_vec_with_elements(&[1i8, 2, 3, 4, 5]);
let collected: Vec<i8> = vec.iter().collect();
assert_eq!(collected, vec![1, 2, 3, 4, 5]);
let sum: i8 = vec.iter().sum();
assert_eq!(sum, 15);
}
#[test]
fn test_iter_size_hint() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let mut iter = vec.iter();
assert_eq!(iter.size_hint(), (3, Some(3)));
iter.next();
assert_eq!(iter.size_hint(), (2, Some(2)));
}
#[test]
fn test_into_iter() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let collected: Vec<i8> = vec.into_iter().collect();
assert_eq!(collected, vec![1, 2, 3]);
}
#[test]
fn test_into_iter_ref() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let collected: Vec<i8> = (&vec).into_iter().collect();
assert_eq!(collected, vec![1, 2, 3]);
assert_eq!(vec.len(), 3); }
#[test]
fn test_into_iter_mut() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
for elem in &mut vec {
*elem *= 2;
}
assert_eq!(vec.get(0), Some(2));
assert_eq!(vec.get(1), Some(4));
assert_eq!(vec.get(2), Some(6));
}
#[test]
fn test_from_vec() {
let vec = vec![1i8, 2, 3, 4, 5];
let compact: CompactVec<i8> = vec.into();
assert_eq!(compact.len(), 5);
assert!(compact.is_inline());
assert_eq!(compact.get(0), Some(1));
assert_eq!(compact.get(4), Some(5));
}
#[test]
fn test_from_array() {
let array = [1i8, 2, 3, 4, 5];
let compact: CompactVec<i8> = array.into();
assert_eq!(compact.len(), 5);
assert_eq!(compact.get(0), Some(1));
assert_eq!(compact.get(4), Some(5));
}
#[test]
fn test_from_array_ref() {
let array = [1i8, 2, 3, 4, 5];
let compact: CompactVec<i8> = (&array).into();
assert_eq!(compact.len(), 5);
assert_eq!(compact.get(0), Some(1));
assert_eq!(compact.get(4), Some(5));
}
#[test]
fn test_from_slice() {
let slice = &[1i8, 2, 3];
let compact: CompactVec<i8> = slice.into();
assert_eq!(compact.len(), 3);
assert_eq!(compact.get(0), Some(1));
assert_eq!(compact.get(2), Some(3));
}
#[test]
fn test_into_vec() {
let compact = test_vec_with_elements(&[1i8, 2, 3]);
let vec: Vec<i8> = compact.into();
assert_eq!(vec, vec![1, 2, 3]);
}
#[test]
fn test_deref_i8() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let slice: &[i8] = &vec;
assert_eq!(slice, &[1, 2, 3]);
}
#[test]
fn test_index_i8() {
let vec = test_vec_with_elements(&[10i8, 20, 30]);
assert_eq!(vec[0], 10);
assert_eq!(vec[1], 20);
assert_eq!(vec[2], 30);
}
#[test]
#[should_panic(expected = "index out of bounds")]
fn test_index_out_of_bounds() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let _ = vec[3];
}
#[test]
fn test_as_ref_i8() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let slice: &[i8] = vec.as_ref();
assert_eq!(slice, &[1, 2, 3]);
}
#[test]
fn test_as_mut_trait() {
let mut vec = test_vec_with_elements(&[1i8, 2, 3]);
let slice: &mut [i8] = vec.as_mut();
slice[1] = 42;
assert_eq!(vec.get(1), Some(42));
}
#[test]
fn test_heap_operations() {
let mut vec: CompactVec<i8> = CompactVec::new();
for i in 0..10 {
vec.push(i);
}
assert!(!vec.is_inline());
assert_eq!(vec.len(), 10);
assert_eq!(vec.pop(), Some(9));
assert_eq!(vec.get(5), Some(5));
vec.insert(5, 42);
assert_eq!(vec.get(5), Some(42));
let removed = vec.remove(5);
assert_eq!(removed, 42);
}
#[test]
fn test_empty_operations() {
let mut vec: CompactVec<i8> = CompactVec::new();
assert_eq!(vec.pop(), None);
assert_eq!(vec.get(0), None);
assert!(vec.is_empty());
assert_eq!(vec.len(), 0);
let iter_count = vec.iter().count();
assert_eq!(iter_count, 0);
}
#[test]
fn test_clone() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let cloned = vec.clone();
assert_eq!(vec.len(), cloned.len());
assert_eq!(vec.is_inline(), cloned.is_inline());
for i in 0..vec.len() {
assert_eq!(vec.get(i), cloned.get(i));
}
}
#[test]
fn test_u8_specialization() {
let mut vec: CompactVec<u8> = CompactVec::new();
vec.extend_from_slice(&[1u8, 2, 3]);
let slice: &[u8] = &vec;
assert_eq!(slice, &[1u8, 2, 3]);
assert_eq!(vec[1], 2u8);
let slice: &[u8] = vec.as_ref();
assert_eq!(slice, &[1u8, 2, 3]);
}
#[test]
fn test_debug() {
let vec = test_vec_with_elements(&[1i8, 2, 3]);
let debug_str = format!("{:?}", vec);
assert!(!debug_str.is_empty());
}
#[test]
fn test_from_iterator() {
let iter = 0..5;
let vec: CompactVec<i8> = iter.collect();
assert_eq!(vec.len(), 5);
assert_eq!(vec.as_slice(), &[0, 1, 2, 3, 4]);
let empty_iter: std::vec::IntoIter<i8> = Vec::new().into_iter();
let empty_vec: CompactVec<i8> = empty_iter.collect();
assert_eq!(empty_vec.len(), 0);
}
#[test]
fn test_transition_preserves_order() {
let mut vec: CompactVec<i8> = CompactVec::new();
for i in 0..INLINE_CAPACITY {
vec.push((i * 10) as i8);
}
assert!(vec.is_inline());
vec.push((INLINE_CAPACITY * 10) as i8);
assert!(!vec.is_inline());
for i in 0..=INLINE_CAPACITY {
assert_eq!(vec.get(i), Some((i as i8) * 10));
}
}
}