#![no_std]
#![warn(missing_docs)]
#![warn(rust_2018_idioms)]
#![warn(rustdoc::all)]
#[cfg(test)]
extern crate std;
extern crate alloc;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::{repeat_with, FromIterator};
use core::mem;
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{Index, IndexMut, RangeBounds};
use alloc::collections::VecDeque;
use alloc::vec::Vec;
mod external_trait_impls;
mod iter;
pub mod vc {
pub use super::iter::*;
}
const fn default_r() -> usize {
#[cfg(any(test, miri))]
return 4;
#[cfg(not(any(test, miri)))]
return 8;
}
pub type Vc<T> = CustomVc<T, { default_r() }>;
pub struct CustomVc<T, const R: usize = { default_r() }> {
new_tail: VecDeque<T>,
old_head: Option<VecDeque<T>>,
}
impl<T: Clone, const R: usize> Clone for CustomVc<T, R> {
fn clone(&self) -> CustomVc<T, R> {
self.iter().cloned().collect()
}
fn clone_from(&mut self, other: &Self) {
self.clear();
self.new_tail.reserve(other.len());
self.new_tail.extend(other.iter().cloned());
}
}
impl<T, const R: usize> Default for CustomVc<T, R> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T, const R: usize> CustomVc<T, R> {
pub fn new() -> Self {
Self {
new_tail: VecDeque::new(),
old_head: None,
}
}
pub const fn move_amount() -> usize {
R
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
new_tail: VecDeque::with_capacity(capacity),
old_head: None,
}
}
#[inline]
pub fn first(&self) -> Option<&T> {
self.get(0)
}
#[inline]
pub fn first_mut(&mut self) -> Option<&mut T> {
self.get_mut(0)
}
#[inline]
pub fn last(&self) -> Option<&T> {
let len = self.len();
if len == 0 {
None
} else {
Some(self.get(len - 1).unwrap())
}
}
#[inline]
pub fn last_mut(&mut self) -> Option<&mut T> {
let len = self.len();
if len == 0 {
None
} else {
Some(self.get_mut(len - 1).unwrap())
}
}
pub fn get(&self, index: usize) -> Option<&T> {
let old_len = self.old_len();
if index < old_len {
let old = unsafe { self.old_ref() };
Some(unsafe { old.get(index).unwrap_unchecked() })
} else {
self.new_tail.get(index - old_len)
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
let old_len = self.old_len();
if index < old_len {
let old = unsafe { self.old_mut() };
Some(unsafe { old.get_mut(index).unwrap_unchecked() })
} else {
self.new_tail.get_mut(index - old_len)
}
}
pub fn swap(&mut self, i: usize, j: usize) {
let old_len = self.old_len();
let i_in_old = i < old_len;
if i_in_old == (j < old_len) {
if i_in_old {
unsafe { self.old_mut() }.swap(i, j);
} else {
self.new_tail.swap(i - old_len, j - old_len);
}
} else if i_in_old {
debug_assert!(self.old_head.is_some());
let old_mut = unsafe { self.old_head.as_mut().unwrap_unchecked() };
mem::swap(&mut old_mut[i], &mut self.new_tail[j - old_len])
} else {
debug_assert!(self.old_head.is_some());
let old_mut = unsafe { self.old_head.as_mut().unwrap_unchecked() };
mem::swap(&mut old_mut[j], &mut self.new_tail[i - old_len])
}
}
#[inline]
pub fn reverse(&mut self) {
self.new_tail.make_contiguous().reverse();
if let Some(ref mut old_head) = self.old_head {
while let Some(e) = old_head.pop_back() {
self.new_tail.push_back(e);
}
let _ = self.take_old();
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.new_tail.capacity()
}
pub fn reserve_exact(&mut self, additional: usize) {
let need = self.old_len() + additional;
if self.new_tail.capacity() - self.new_tail.len() > need {
if cfg!(debug_assertions) {
let buckets = self.new_tail.capacity();
self.new_tail.reserve_exact(need);
assert_eq!(
buckets,
self.new_tail.capacity(),
"resize despite sufficient capacity"
);
} else {
self.new_tail.reserve_exact(need);
}
} else if self.old_len() != 0 {
self.carry_all();
self.grow(additional, true);
} else {
self.grow(additional, true);
}
}
pub fn reserve(&mut self, additional: usize) {
let need = self.old_len() + additional;
if self.new_tail.capacity() - self.new_tail.len() > need {
if cfg!(debug_assertions) {
let buckets = self.new_tail.capacity();
self.new_tail.reserve(need);
assert_eq!(
buckets,
self.new_tail.capacity(),
"resize despite sufficient capacity"
);
} else {
self.new_tail.reserve(need);
}
} else if self.old_len() != 0 {
self.carry_all();
self.grow(additional, false);
} else {
self.grow(additional, false);
}
}
pub fn shrink_to_fit(&mut self) {
self.shrink_to(0);
}
pub fn shrink_to(&mut self, min_capacity: usize) {
let mut need = self.new_tail.len();
if self.old_head.is_some() {
let old_len = self.old_len();
need += old_len;
need += old_len.div_ceil(R);
} else if min_capacity <= need {
self.new_tail.shrink_to_fit();
}
let min_size = usize::max(need, min_capacity);
self.new_tail.shrink_to(min_size);
}
pub fn truncate(&mut self, len: usize) {
let old_len = self.old_len();
if old_len == 0 {
self.new_tail.truncate(len);
} else if len < old_len {
self.new_tail.clear();
for v in unsafe { self.take_old_unchecked() }.into_iter().take(len) {
self.new_tail.push_back(v);
}
} else {
self.new_tail.truncate(len - old_len);
for v in unsafe { self.take_old_unchecked() }.into_iter().rev() {
self.new_tail.push_front(v);
}
}
}
pub fn iter(&self) -> iter::Iter<'_, T> {
iter::Iter {
head: self.old_head.as_ref().map(|v| v.iter()),
tail: self.new_tail.iter(),
}
}
pub fn iter_mut(&mut self) -> iter::IterMut<'_, T> {
iter::IterMut {
head: self.old_head.as_mut().map(|v| v.iter_mut()),
tail: self.new_tail.iter_mut(),
}
}
#[inline]
pub fn as_single_slice(&self) -> Option<&[T]> {
if self.old_len() != 0 {
None
} else if let (tail, []) = self.new_tail.as_slices() {
Some(tail)
} else {
None
}
}
pub fn len(&self) -> usize {
self.new_tail.len() + self.old_len()
}
pub fn is_empty(&self) -> bool {
self.new_tail.is_empty() && self.old_len() == 0
}
#[inline]
fn range_start_end<Range>(&self, range: Range) -> (usize, usize)
where
Range: RangeBounds<usize>,
{
let len = self.len();
let start = match range.start_bound() {
Included(&n) => n,
Excluded(&n) => n + 1,
Unbounded => 0,
};
let end = match range.end_bound() {
Included(&n) => n + 1,
Excluded(&n) => n,
Unbounded => len,
};
assert!(start <= end, "lower bound was too large");
assert!(end <= len, "upper bound was too large");
(start, end)
}
#[inline]
fn range_start_end_split<Range>(
&self,
range: Range,
) -> (Option<(usize, usize)>, Option<(usize, usize)>)
where
Range: RangeBounds<usize>,
{
let (start_incl, end_excl) = self.range_start_end(range);
let old_len = self.old_len();
if old_len == 0 {
return (None, Some((start_incl, end_excl)));
}
debug_assert!(start_incl <= end_excl);
let head = if start_incl < old_len {
debug_assert!(self.old_head.is_some());
Some((start_incl, end_excl.min(old_len)))
} else {
None
};
let tail = if end_excl > old_len {
if start_incl > old_len {
Some((start_incl - old_len, end_excl - old_len))
} else {
Some((0, (end_excl - old_len)))
}
} else {
None
};
(head, tail)
}
#[inline]
pub fn range<Range>(&self, range: Range) -> iter::Iter<'_, T>
where
Range: RangeBounds<usize>,
{
let (head, tail) = self.range_start_end_split(range);
let head = if let Some((start_incl, end_excl)) = head {
debug_assert!(self.old_head.is_some());
let old_mut = unsafe { self.old_head.as_ref().unwrap_unchecked() };
Some(old_mut.range(start_incl..end_excl))
} else {
None
};
let tail = if let Some((start_incl, end_excl)) = tail {
self.new_tail.range(start_incl..end_excl)
} else {
self.new_tail.range(..0)
};
iter::Iter { head, tail }
}
#[inline]
pub fn range_mut<Range>(&mut self, range: Range) -> iter::IterMut<'_, T>
where
Range: RangeBounds<usize>,
{
let (head, tail) = self.range_start_end_split(range);
let head = if let Some((start_incl, end_excl)) = head {
debug_assert!(self.old_head.is_some());
let old_mut = unsafe { self.old_head.as_mut().unwrap_unchecked() };
Some(old_mut.range_mut(start_incl..end_excl))
} else {
None
};
let tail = if let Some((start_incl, end_excl)) = tail {
self.new_tail.range_mut(start_incl..end_excl)
} else {
self.new_tail.range_mut(..0)
};
iter::IterMut { head, tail }
}
#[inline]
pub fn drain<Range>(&mut self, range: Range) -> iter::Drain<'_, T>
where
Range: RangeBounds<usize>,
{
let (head, tail) = self.range_start_end_split(range);
let head = if let Some((start_incl, end_excl)) = head {
debug_assert!(self.old_head.is_some());
let old_mut = unsafe { self.old_head.as_mut().unwrap_unchecked() };
Some(old_mut.drain(start_incl..end_excl))
} else {
None
};
let tail = if let Some((start_incl, end_excl)) = tail {
self.new_tail.drain(start_incl..end_excl)
} else {
self.new_tail.drain(..0)
};
iter::Drain { head, tail }
}
#[inline]
pub fn clear(&mut self) {
let _ = self.take_old();
self.new_tail.clear();
}
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq<T>,
{
self.new_tail.contains(x) || self.old_head.as_ref().is_some_and(|v| v.contains(x))
}
pub fn front(&self) -> Option<&T> {
self.old_head
.as_ref()
.and_then(|v| v.front())
.or_else(|| self.new_tail.front())
}
pub fn front_mut(&mut self) -> Option<&mut T> {
if let Some(e) = self.old_head.as_mut().and_then(|v| v.front_mut()) {
Some(e)
} else {
self.new_tail.front_mut()
}
}
pub fn back(&self) -> Option<&T> {
self.new_tail
.back()
.or_else(|| self.old_head.as_ref().and_then(|v| v.back()))
}
pub fn back_mut(&mut self) -> Option<&mut T> {
if let Some(e) = self.new_tail.back_mut() {
Some(e)
} else {
self.old_head.as_mut().and_then(|v| v.back_mut())
}
}
pub fn pop_front(&mut self) -> Option<T> {
let new_tail = &mut self.new_tail;
self.old_head
.as_mut()
.and_then(|v| v.pop_front())
.or_else(|| new_tail.pop_front())
}
pub fn pop_back(&mut self) -> Option<T> {
let old_head = &mut self.old_head;
self.new_tail
.pop_back()
.or_else(|| old_head.as_mut().and_then(|v| v.pop_back()))
}
#[inline]
pub fn pop(&mut self) -> Option<T> {
self.pop_back()
}
pub fn push_back(&mut self, value: T) {
if self.new_tail.capacity() == self.new_tail.len() {
debug_assert_eq!(self.old_len(), 0);
self.grow(1 , false);
return self.push_back(value);
}
if cfg!(debug_assertions) {
let cap = self.new_tail.capacity();
self.new_tail.push_back(value);
assert_eq!(
cap,
self.new_tail.capacity(),
"resize while elements are still left over"
);
} else {
self.new_tail.push_back(value);
}
if self.old_len() != 0 {
self.carry();
}
}
#[inline]
pub fn push(&mut self, value: T) {
self.push_back(value)
}
#[inline]
unsafe fn old_ref(&self) -> &VecDeque<T> {
debug_assert!(self.old_head.is_some());
unsafe { self.old_head.as_ref().unwrap_unchecked() }
}
#[inline]
unsafe fn old_mut(&mut self) -> &mut VecDeque<T> {
debug_assert!(self.old_head.is_some());
unsafe { self.old_head.as_mut().unwrap_unchecked() }
}
#[inline]
fn old_len(&self) -> usize {
self.old_head.as_ref().map_or(0, |v| v.len())
}
#[inline]
#[doc(hidden)]
#[allow(dead_code)]
pub fn is_atoning(&self) -> bool {
self.old_head.is_some()
}
pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
let length = self.len();
if length > 0 && index < length && index != 0 {
self.swap(index, 0);
} else if index >= length {
return None;
}
self.pop_front()
}
pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
let length = self.len();
if length > 0 && index < length - 1 {
self.swap(index, length - 1);
} else if index >= length {
return None;
}
self.pop_back()
}
#[inline]
pub fn swap_remove(&mut self, index: usize) -> T {
self.swap_remove_back(index).expect("index out of bounds")
}
pub fn insert(&mut self, index: usize, value: T) {
let do_the_thing = |this: &mut Self, value: T| {
let old_len = this.old_len();
if index < old_len {
let old = unsafe { this.old_mut() };
let shift = unsafe { old.pop_back().unwrap_unchecked() };
this.new_tail.push_front(shift);
unsafe { this.old_mut() }.insert(index, value);
} else {
this.new_tail.insert(index - old_len, value);
}
};
if self.old_len() != 0 {
if cfg!(debug_assertions) {
let cap = self.new_tail.capacity();
do_the_thing(self, value);
assert_eq!(
cap,
self.new_tail.capacity(),
"resize while elements are still left over"
);
} else {
do_the_thing(self, value);
}
self.carry();
} else if self.new_tail.capacity() == self.new_tail.len() {
self.grow(1 , false);
self.insert(index, value)
} else {
do_the_thing(self, value);
}
}
pub fn push_front(&mut self, value: T) {
self.insert(0, value);
}
pub fn remove(&mut self, index: usize) -> T {
#[cold]
#[inline(never)]
fn assert_failed(index: usize, len: usize) -> ! {
panic!("removal index (is {}) should be < len (is {})", index, len);
}
let old_len = self.old_len();
if index < old_len {
unsafe {
let v = self.old_mut().remove(index);
if self.old_ref().is_empty() {
let _ = self.take_old_unchecked();
}
v.unwrap_or_else(|| assert_failed(index, self.len()))
}
} else {
self.new_tail
.remove(index - old_len)
.unwrap_or_else(|| assert_failed(index, self.len()))
}
}
#[inline]
#[must_use = "use `.truncate()` if you don't need the other half"]
pub fn split_off(&mut self, at: usize) -> Self {
let old_len = self.old_len();
if at < old_len {
let mut keep = self.old_head.take().unwrap();
let tail_of_old = keep.split_off(at);
let give_away = mem::replace(&mut self.new_tail, keep);
Self {
new_tail: give_away,
old_head: Some(tail_of_old),
}
} else {
let give_away = self.new_tail.split_off(at);
Self {
new_tail: give_away,
old_head: None,
}
}
}
#[inline]
pub fn append(&mut self, other: &mut Self) {
self.reserve(other.len());
while let Some(e) = other.pop_front() {
self.push_back(e);
}
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
if let Some(ref mut v) = self.old_head {
v.retain(&mut f);
}
self.new_tail.retain(&mut f);
}
fn take_old(&mut self) -> Option<VecDeque<T>> {
self.old_head.take()
}
unsafe fn take_old_unchecked(&mut self) -> VecDeque<T> {
unsafe { self.old_head.take().unwrap_unchecked() }
}
#[inline(never)]
fn grow(&mut self, extra: usize, exact: bool) {
debug_assert_eq!(self.old_len(), 0);
let need = self.new_tail.len();
let pushes = self.new_tail.len().div_ceil(R);
let add = usize::max(extra, pushes);
let new_tail = if exact {
let mut v = VecDeque::with_capacity(0);
v.reserve_exact(need + pushes + add);
v
} else {
VecDeque::with_capacity(need + pushes + add)
};
self.old_head = Some(mem::replace(&mut self.new_tail, new_tail));
}
pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut() -> T) {
let len = self.len();
if new_len > len {
self.extend(repeat_with(generator).take(new_len - len))
} else {
self.truncate(new_len);
}
}
pub fn make_contiguous(&mut self) -> &mut [T] {
if self.old_len() != 0 {
self.carry_all();
}
self.new_tail.make_contiguous()
}
}
impl<T: Clone, const R: usize> CustomVc<T, R> {
pub fn resize(&mut self, new_len: usize, value: T) {
self.resize_with(new_len, || value.clone());
}
}
impl<A: PartialEq, const R: usize> PartialEq for CustomVc<A, R> {
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false;
}
match (self.old_len(), other.old_len()) {
(0, 0) => self.new_tail == other.new_tail,
(self_old_len, other_old_len) => {
if self_old_len == other_old_len {
return self.old_head == other.old_head && self.new_tail == other.new_tail;
}
self.old_head
.iter()
.flatten()
.chain(self.new_tail.iter())
.eq(other.old_head.iter().flatten().chain(other.new_tail.iter()))
}
}
}
}
impl<A: Eq, const R: usize> Eq for CustomVc<A, R> {}
macro_rules! __impl_slice_eq1 {
($lhs:ty, $rhs:ty, $($constraints:tt)*) => {
impl<A, B, const R: usize> PartialEq<$rhs> for $lhs
where
A: PartialEq<B>,
$($constraints)*
{
fn eq(&self, other: &$rhs) -> bool {
self.old_head
.iter()
.flatten()
.chain(self.new_tail.iter())
.eq(other.iter())
}
}
}
}
__impl_slice_eq1! { CustomVc<A, R>, Vec<B>, }
__impl_slice_eq1! { CustomVc<A, R>, &[B], }
__impl_slice_eq1! { CustomVc<A, R>, &mut [B], }
macro_rules! __impl_slice_eq2 {
($lhs:ty, $rhs:ty, $($constraints:tt)*) => {
impl<A, B, const R: usize> PartialEq<$lhs> for $rhs
where
A: PartialEq<B>,
$($constraints)*
{
fn eq(&self, other: &$lhs) -> bool {
other.old_head
.iter()
.flatten()
.chain(other.new_tail.iter())
.eq(self.iter())
}
}
}
}
__impl_slice_eq2! { CustomVc<A, R>, Vec<B>, }
__impl_slice_eq2! { CustomVc<A, R>, &[B], }
__impl_slice_eq2! { CustomVc<A, R>, &mut [B], }
impl<A: PartialOrd, const R: usize> PartialOrd for CustomVc<A, R> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (self.old_len(), other.old_len()) {
(0, 0) => self.new_tail.partial_cmp(&other.new_tail),
(self_old_len, other_old_len) => {
if self_old_len == other_old_len {
return self.old_head.partial_cmp(&other.old_head).and_then(|o| {
if let Ordering::Equal = o {
self.new_tail.partial_cmp(&other.new_tail)
} else {
Some(o)
}
});
}
self.old_head
.iter()
.flatten()
.chain(self.new_tail.iter())
.partial_cmp(other.old_head.iter().flatten().chain(other.new_tail.iter()))
}
}
}
}
impl<A: Ord, const R: usize> Ord for CustomVc<A, R> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
match (self.old_len(), other.old_len()) {
(0, 0) => self.new_tail.cmp(&other.new_tail),
(self_old_len, other_old_len) => {
if self_old_len == other_old_len {
return self
.old_head
.cmp(&other.old_head)
.then_with(|| self.new_tail.cmp(&other.new_tail));
}
self.old_head
.iter()
.flatten()
.chain(self.new_tail.iter())
.cmp(other.old_head.iter().flatten().chain(other.new_tail.iter()))
}
}
}
}
impl<A: Hash, const R: usize> Hash for CustomVc<A, R> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
self.old_head.hash(state);
self.new_tail.hash(state);
}
}
impl<A, const R: usize> Index<usize> for CustomVc<A, R> {
type Output = A;
#[inline]
fn index(&self, index: usize) -> &A {
self.get(index).expect("Out of bounds access")
}
}
impl<A, const R: usize> IndexMut<usize> for CustomVc<A, R> {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut A {
self.get_mut(index).expect("Out of bounds access")
}
}
impl<A, const R: usize> FromIterator<A> for CustomVc<A, R> {
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
let iterator = iter.into_iter();
let (lower, _) = iterator.size_hint();
let mut deq = Self::with_capacity(lower);
deq.extend(iterator);
deq
}
}
impl<T, const R: usize> IntoIterator for CustomVc<T, R> {
type Item = T;
type IntoIter = iter::IntoIter<T>;
fn into_iter(self) -> iter::IntoIter<T> {
iter::IntoIter {
head: self.old_head.map(|v| v.into_iter()),
tail: self.new_tail.into_iter(),
}
}
}
impl<'a, T, const R: usize> IntoIterator for &'a CustomVc<T, R> {
type Item = &'a T;
type IntoIter = iter::Iter<'a, T>;
fn into_iter(self) -> iter::Iter<'a, T> {
self.iter()
}
}
impl<'a, T, const R: usize> IntoIterator for &'a mut CustomVc<T, R> {
type Item = &'a mut T;
type IntoIter = iter::IterMut<'a, T>;
fn into_iter(self) -> iter::IterMut<'a, T> {
self.iter_mut()
}
}
impl<A, const R: usize> Extend<A> for CustomVc<A, R> {
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
let iter = iter.into_iter();
let reserve = if self.is_empty() {
iter.size_hint().0
} else {
iter.size_hint().0.div_ceil(2)
};
self.reserve(reserve);
iter.for_each(move |v| {
self.push_back(v);
});
}
}
impl<'a, T: 'a + Copy, const R: usize> Extend<&'a T> for CustomVc<T, R> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
}
}
impl<T: fmt::Debug, const R: usize> fmt::Debug for CustomVc<T, R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self).finish()
}
}
impl<T, const R: usize> From<Vec<T>> for CustomVc<T, R> {
fn from(other: Vec<T>) -> Self {
Self::from(VecDeque::from(other))
}
}
impl<T, const R: usize> From<VecDeque<T>> for CustomVc<T, R> {
fn from(other: VecDeque<T>) -> Self {
Self {
new_tail: other,
old_head: None,
}
}
}
impl<T, const R: usize> From<CustomVc<T, R>> for Vec<T> {
fn from(other: CustomVc<T, R>) -> Self {
VecDeque::from(other).into()
}
}
impl<T, const R: usize> From<CustomVc<T, R>> for VecDeque<T> {
fn from(mut other: CustomVc<T, R>) -> Self {
if other.old_len() != 0 {
other.carry_all();
}
other.new_tail
}
}
impl<T, const R: usize> CustomVc<T, R> {
#[cold]
#[inline(never)]
pub(crate) fn carry_all(&mut self) {
debug_assert_ne!(self.old_len(), 0);
while let Some(e) = unsafe { self.old_mut() }.pop_back() {
self.new_tail.push_front(e);
}
self.old_head = None;
}
#[cold]
#[inline(never)]
pub(crate) fn carry(&mut self) {
if !unsafe { self.old_ref() }.is_empty() {
for _ in 0..R {
if let Some(e) = unsafe { self.old_mut() }.pop_back() {
self.new_tail.push_front(e);
} else {
self.old_head = None;
return;
}
}
if unsafe { self.old_ref() }.is_empty() {
self.old_head = None;
}
}
}
}
#[cfg(test)]
#[cfg(not(tarpaulin_include))] mod tests {
use super::Vc;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::vec::Vec;
use std::{format, thread_local, vec};
#[test]
fn zero_capacities() {
assert_eq!(VecDeque::<i32>::with_capacity(0).capacity(), 0);
assert_eq!(Vc::<i32>::with_capacity(0).capacity(), 0);
}
#[test]
fn create_capacity_zero() {
let mut m = Vc::with_capacity(0);
m.push(1);
m.push(2);
assert_eq!(m.front(), Some(&1));
assert_eq!(m.back(), Some(&2));
assert!(m.contains(&1));
assert!(m.contains(&2));
assert!(!m.contains(&0));
}
#[test]
fn push() {
let mut m = Vc::new();
assert_eq!(m.len(), 0);
m.push(1);
assert_eq!(m.len(), 1);
m.push(2);
assert_eq!(m.len(), 2);
assert_eq!(*m.front().unwrap(), 1);
assert_eq!(*m.back().unwrap(), 2);
}
#[test]
fn split_push() {
assert_eq!(Vc::<i32>::move_amount(), 4);
let mut m = Vc::with_capacity(3);
assert_eq!(m.capacity(), 3);
assert_eq!(m.len(), 0);
for i in 1..=3 {
m.push(i);
assert!(m.contains(&i));
assert_eq!(m.capacity(), 3);
}
assert!(m.iter().copied().eq(1..=3));
assert!(!m.is_atoning());
m.push(4);
assert_eq!(m.capacity(), 5);
let n = m.new_tail.len();
m.new_tail.reserve_exact(7 - n);
assert_eq!(m.capacity(), 7);
assert!(!m.is_atoning());
assert_eq!(m.old_head, None);
assert_eq!(m.new_tail.len(), 4);
for i in 1..=4 {
assert!(m.contains(&i));
}
assert!(m.iter().copied().eq(1..=4));
for i in 5..=7 {
m.push(i);
assert!(m.contains(&i));
assert_eq!(m.capacity(), 7);
}
assert!(m.iter().copied().eq(1..=7));
m.push(8);
assert_eq!(m.capacity(), 11);
let n = m.new_tail.len();
m.new_tail.reserve_exact(15 - n);
assert_eq!(m.capacity(), 15);
assert!(m.is_atoning());
assert_eq!(m.new_tail.len(), 1 + Vc::<()>::move_amount());
assert_eq!(m.old_len(), 8 - (1 + Vc::<()>::move_amount()));
for i in 1..=8 {
assert!(m.contains(&i));
}
assert_eq!(m.iter().count(), 8);
for i in 1..=8 {
assert!(m.iter().any(|&e| e == i));
}
assert_eq!(m.iter_mut().count(), 8);
for i in 1..=8 {
assert!(m.iter_mut().any(|&mut e| e == i));
}
m.push(9);
assert!(!m.is_atoning());
assert_eq!(m.new_tail.len(), 9);
assert_eq!(m.old_head, None);
assert_eq!(m.capacity(), 15);
for i in 1..=9 {
assert!(m.contains(&i));
}
assert!(m.iter().copied().eq(1..=9));
}
#[test]
fn clone() {
let mut m = Vc::new();
for i in 1..=8 {
assert_eq!(m.len(), i - 1);
m.push(i);
}
assert_eq!(m.len(), 8);
let m2 = m.clone();
assert!(m2.iter().copied().eq(1..=8));
}
#[test]
fn clone_from() {
let mut m = Vc::new();
let mut m2 = Vc::new();
for i in 1..=8 {
assert_eq!(m.len(), i - 1);
m.push(i);
}
assert_eq!(m.len(), 8);
m2.clone_from(&m);
assert!(m2.iter().copied().eq(1..=8));
}
thread_local! { static DROP_VECTOR: RefCell<Vec<i32>> = const {RefCell::new(Vec::new())} }
#[derive(Hash, PartialEq, Eq)]
struct Droppable {
k: usize,
}
impl Droppable {
fn new(k: usize) -> Droppable {
DROP_VECTOR.with(|slot| {
slot.borrow_mut()[k] += 1;
});
Droppable { k }
}
}
impl Drop for Droppable {
fn drop(&mut self) {
DROP_VECTOR.with(|slot| {
slot.borrow_mut()[self.k] -= 1;
});
}
}
impl Clone for Droppable {
fn clone(&self) -> Self {
Droppable::new(self.k)
}
}
#[test]
fn drops() {
DROP_VECTOR.with(|slot| {
*slot.borrow_mut() = vec![0; 100];
});
{
let mut vs = Vc::new();
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 0);
}
});
for i in 0..100 {
let d = Droppable::new(i);
vs.push(d);
}
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 1);
}
});
for i in 0..50 {
let v = vs.remove(0);
assert_eq!(v.k, i);
DROP_VECTOR.with(|v| {
assert_eq!(v.borrow()[i], 1);
});
}
DROP_VECTOR.with(|v| {
for i in 0..50 {
assert_eq!(v.borrow()[i], 0);
}
for i in 50..100 {
assert_eq!(v.borrow()[i], 1);
}
});
}
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 0);
}
});
}
#[test]
fn into_iter_drops() {
DROP_VECTOR.with(|v| {
*v.borrow_mut() = vec![0; 100];
});
let vs = {
let mut vs = Vc::new();
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 0);
}
});
for i in 0..100 {
let d = Droppable::new(i);
vs.push(d);
}
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 1);
}
});
vs
};
drop(vs.clone());
{
let mut half = vs.into_iter().take(50);
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 1);
}
});
for _ in half.by_ref() {}
DROP_VECTOR.with(|v| {
let n = (0..100).filter(|&i| v.borrow()[i] == 1).count();
assert_eq!(n, 50);
});
};
DROP_VECTOR.with(|v| {
for i in 0..100 {
assert_eq!(v.borrow()[i], 0);
}
});
}
#[test]
#[should_panic]
fn empty_remove() {
let mut vs: Vc<i32> = Vc::new();
vs.remove(0);
}
#[test]
fn empty_iter() {
let mut vs: Vc<i32> = Vc::new();
assert_eq!(vs.drain(..).next(), None);
assert_eq!(vs.iter().next(), None);
assert_eq!(vs.iter_mut().next(), None);
assert_eq!(vs.len(), 0);
assert!(vs.is_empty());
assert_eq!(vs.into_iter().next(), None);
}
#[test]
#[should_panic]
fn empty_swap_remove() {
let mut vs: Vc<i32> = Vc::new();
vs.swap_remove(0);
}
#[test]
fn lots_of_pushes() {
let mut vs = Vc::new();
#[cfg(not(any(tarpaulin, miri)))]
const M: usize = 101;
#[cfg(tarpaulin)]
const M: usize = 33;
#[cfg(miri)]
const M: usize = 17;
for i in 1..M {
vs.push(i);
for j in 1..=i {
let r = vs.get(j - 1);
assert_eq!(r, Some(&j));
}
for j in i + 1..M {
let r = vs.get(j - 1);
assert_eq!(r, None);
}
}
for i in M..(M * 2 - 1) {
assert!(!vs.contains(&i));
}
for i in 1..M {
assert_eq!(vs.remove(0), i);
for j in 1..=i {
assert!(!vs.contains(&j));
}
for j in i + 1..M {
assert!(vs.contains(&j));
}
}
for i in 1..M {
assert!(!vs.contains(&i));
}
for i in 1..M {
vs.push(i);
}
for i in (1..M).rev() {
assert_eq!(vs.pop(), Some(i));
for j in i..M {
assert!(!vs.contains(&j));
}
for j in 1..i {
assert!(vs.contains(&j));
}
}
assert!(vs.is_empty());
}
#[test]
fn is_empty() {
let mut vs = Vc::with_capacity(4);
vs.push(1);
assert!(!vs.is_empty());
vs.remove(0);
assert!(vs.is_empty());
}
#[test]
fn iterate() {
let mut vs = Vc::with_capacity(4);
for i in 0..=36 {
vs.push(i * 2);
}
assert!(vs.is_atoning());
assert_eq!(vs.len(), 37);
assert!(vs.iter().copied().eq((0..=36).map(|v| v * 2)));
}
#[test]
fn eq() {
let mut vs1 = Vc::new();
for v in (1..).take(8) {
vs1.push(v);
}
let mut vs2 = Vc::new();
for v in (1..).take(7) {
vs2.push(v);
}
assert!(vs1 != vs2);
vs2.push(8);
assert_eq!(vs1, vs2);
}
#[test]
fn show() {
let mut vs = Vc::new();
let empty: Vc<i32> = Vc::new();
vs.push(1);
vs.push(2);
assert_eq!(format!("{vs:?}"), "[1, 2]");
assert_eq!(format!("{empty:?}"), "[]");
}
#[test]
fn from_iter() {
let xs = 0..8;
let vs: Vc<_> = xs.clone().collect();
assert!(vs.iter().copied().eq(xs));
}
#[test]
fn size_hint() {
let xs = 0..8;
let vs: Vc<_> = xs.clone().collect();
let mut iter = vs.iter();
for _ in iter.by_ref().take(3) {}
assert_eq!(iter.size_hint(), (8 - 3, Some(8 - 3)));
}
#[test]
fn iter_len() {
let xs = 0..8;
let vs: Vc<_> = xs.clone().collect();
let mut iter = vs.iter();
for _ in iter.by_ref().take(3) {}
assert_eq!(iter.len(), 8 - 3);
}
#[test]
fn mut_size_hint() {
let xs = 0..8;
let mut vs: Vc<_> = xs.clone().collect();
let mut iter = vs.iter_mut();
for _ in iter.by_ref().take(3) {}
assert_eq!(iter.size_hint(), (8 - 3, Some(8 - 3)));
}
#[test]
fn iter_mut_len() {
let xs = 0..8;
let mut vs: Vc<_> = xs.clone().collect();
let mut iter = vs.iter_mut();
for _ in iter.by_ref().take(3) {}
assert_eq!(iter.len(), 8 - 3);
}
#[test]
fn index() {
let mut vs = Vc::with_capacity(7);
for i in 1..=8 {
vs.push(i);
}
assert!(vs.is_atoning());
assert_eq!(vs[2 - 1], 2);
}
#[test]
#[should_panic]
fn index_nonexistent() {
let mut vs = Vc::new();
for i in 1..=8 {
vs.push(i);
}
assert!(vs.is_atoning());
let _ = vs[9];
}
#[test]
fn extend_ref() {
let mut a = Vc::new();
a.push("one");
let mut b = Vc::new();
b.push("two");
b.push("three");
a.extend(&b);
assert_eq!(a.len(), 3);
assert_eq!(a[0], "one");
assert_eq!(a[1], "two");
assert_eq!(a[2], "three");
}
#[test]
fn capacity_not_less_than_len() {
let mut a = Vc::new();
let mut item = 0;
for _ in 0..116 {
a.push(item);
item += 1;
}
assert!(a.capacity() > a.len());
let free = a.capacity() - a.len();
for _ in 0..free {
a.push(item);
item += 1;
}
assert_eq!(a.len(), a.capacity());
a.insert(item, 0);
assert!(a.capacity() > a.len());
}
#[test]
fn retain() {
let mut vs: Vc<i32> = Vc::new();
for x in 0..130 {
vs.push(x);
}
assert!(vs.is_atoning());
vs.retain(|&e| e % 2 == 0);
assert_eq!(vs.len(), 65);
assert_eq!(vs[2], 4);
assert_eq!(vs[4], 8);
assert_eq!(vs[6], 12);
}
#[test]
fn type_inference() {
let mut vc_default = Vc::default();
vc_default.push(0usize);
}
}