#![no_std]
#![feature(fixed_size_array)]
use core::array::FixedSizeArray;
use core::fmt::{self, Debug};
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::{mem, ptr};
struct FixedCapacityDequeLike<T, A: FixedSizeArray<T>> {
array: MaybeUninit<A>,
begining: usize,
end: usize,
_element: PhantomData<T>,
}
impl<T, A: FixedSizeArray<T>> FixedCapacityDequeLike<T, A> {
fn new() -> FixedCapacityDequeLike<T, A> {
FixedCapacityDequeLike {
array: MaybeUninit::uninit(),
begining: 0,
end: 0,
_element: PhantomData,
}
}
fn from_array(array: A) -> FixedCapacityDequeLike<T, A> {
let length = array.as_slice().len();
FixedCapacityDequeLike {
array: MaybeUninit::new(array),
begining: 0,
end: length,
_element: PhantomData,
}
}
fn capacity(&self) -> usize {
unsafe { (*self.array.as_ptr()).as_slice().len() }
}
fn length(&self) -> usize {
self.end - self.begining
}
fn is_empty(&self) -> bool {
self.length() == 0
}
fn is_full(&self) -> bool {
self.length() == self.capacity()
}
fn push_back(&mut self, element: T) {
if self.end < self.capacity() {
let item_index = self.end;
let slice = unsafe { (*self.array.as_mut_ptr()).as_mut_slice() };
unsafe {
ptr::write(slice.get_unchecked_mut(item_index), element);
}
self.end += 1;
} else {
panic!("No capacity left at the end.");
}
}
#[allow(dead_code)]
fn push_front(&mut self, element: T) {
if self.begining != 0 {
let item_index = self.begining - 1;
let slice = unsafe { (*self.array.as_mut_ptr()).as_mut_slice() };
unsafe {
ptr::write(slice.get_unchecked_mut(item_index), element);
}
self.begining -= 1;
} else {
panic!("No capacity left at the begining.")
}
}
fn pop_back(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
let item_index = self.end - 1;
let item = unsafe {
let slice = (*self.array.as_ptr()).as_slice();
ptr::read(slice.get_unchecked(item_index))
};
self.end -= 1;
Some(item)
}
}
fn pop_front(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
let item_index = self.begining;
let item = unsafe {
let slice = (*self.array.as_ptr()).as_slice();
ptr::read(slice.get_unchecked(item_index))
};
self.begining += 1;
Some(item)
}
}
fn try_extract_array(&mut self) -> Option<A> {
if self.length() == self.capacity() {
let array_shallow_copy = unsafe { ptr::read(self.array.as_ptr()) };
self.begining = 0;
self.end = 0;
Some(array_shallow_copy)
} else {
None
}
}
fn as_slice(&self) -> &[T] {
unsafe { &(*self.array.as_ptr()).as_slice()[self.begining..self.end] }
}
fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { &mut (*self.array.as_mut_ptr()).as_mut_slice()[self.begining..self.end] }
}
}
impl<T, A: FixedSizeArray<T>> Drop for FixedCapacityDequeLike<T, A> {
fn drop(&mut self) {
while let Some(item) = self.pop_back() {
mem::drop(item);
}
}
}
impl<T, A: FixedSizeArray<T>> Debug for FixedCapacityDequeLike<T, A>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FixedCapacityDequeLike")
.field("array", &self.as_slice())
.field("begining", &self.begining)
.field("end", &self.end)
.field("_element", &self._element)
.finish()
}
}
impl<T, A: FixedSizeArray<T>> PartialEq for FixedCapacityDequeLike<T, A>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.capacity() == other.capacity()
&& self.begining == other.begining
&& self.end == other.end
&& self.as_slice() == other.as_slice()
}
}
impl<T, A: FixedSizeArray<T>> Eq for FixedCapacityDequeLike<T, A> where T: Eq {}
impl<T, A: FixedSizeArray<T>> Clone for FixedCapacityDequeLike<T, A>
where
T: Clone,
{
fn clone(&self) -> Self {
let mut clone = FixedCapacityDequeLike {
array: MaybeUninit::uninit(),
begining: self.begining,
end: self.end,
_element: PhantomData,
};
unsafe {
for (src, dst) in self.as_slice().iter().zip(clone.as_mut_slice()) {
ptr::write(dst, src.clone());
}
}
clone
}
}
pub fn try_init_from_iterator<T, A, I>(mut iter: I) -> Option<A>
where
A: FixedSizeArray<T>,
I: Iterator<Item = T>,
{
let mut deque = FixedCapacityDequeLike::new();
loop {
if deque.is_full() {
break deque.try_extract_array();
} else {
if let Some(item) = iter.next() {
deque.push_back(item)
} else {
break None;
}
}
}
}
pub fn try_init_from_slice<T, A>(slice: &[T]) -> Option<A>
where
A: FixedSizeArray<T>,
T: Clone,
{
if length_of::<T, A>() <= slice.len() {
try_init_from_iterator(slice.iter().cloned())
} else {
None
}
}
pub fn init_with<T, A, F>(mut initializer_fn: F) -> A
where
A: FixedSizeArray<T>,
F: FnMut() -> T,
{
let mut deque = FixedCapacityDequeLike::new();
while !deque.is_full() {
deque.push_back(initializer_fn());
}
deque.try_extract_array().unwrap()
}
pub fn indexed_init_with<T, A, F>(mut initializer_fn: F) -> A
where
A: FixedSizeArray<T>,
F: FnMut(usize) -> T,
{
let mut deque = FixedCapacityDequeLike::new();
let mut idx = 0;
while !deque.is_full() {
deque.push_back(initializer_fn(idx));
idx += 1
}
deque.try_extract_array().unwrap()
}
pub fn length_of<T, A: FixedSizeArray<T>>() -> usize {
let array: MaybeUninit<A> = MaybeUninit::uninit();
unsafe { (*array.as_ptr()).as_slice().len() }
}
pub fn split<T, A: FixedSizeArray<T>, LEFT: FixedSizeArray<T>, RIGHT: FixedSizeArray<T>>(
array: A,
) -> (LEFT, RIGHT) {
assert_eq!(
array.as_slice().len(),
length_of::<T, LEFT>() + length_of::<T, RIGHT>(),
"Sum of outputs' lengths is not equal to length of input."
);
let mut iter = ArrayIntoIterator::new(array);
let left: LEFT = try_init_from_iterator(iter.by_ref()).unwrap();
let right: RIGHT = try_init_from_iterator(iter.by_ref()).unwrap();
(left, right)
}
pub fn join<T, A: FixedSizeArray<T>, LEFT: FixedSizeArray<T>, RIGHT: FixedSizeArray<T>>(
left: LEFT,
right: RIGHT,
) -> A {
assert_eq!(
length_of::<T, A>(),
left.as_slice().len() + right.as_slice().len(),
"Sum of inputs' lengths is not equal to output length."
);
let left_iter = ArrayIntoIterator::new(left);
let right_iter = ArrayIntoIterator::new(right);
try_init_from_iterator(left_iter.chain(right_iter)).unwrap()
}
pub struct ArrayIntoIterator<T, A: FixedSizeArray<T>> {
deque: FixedCapacityDequeLike<T, A>,
}
impl<T, A: FixedSizeArray<T>> PartialEq for ArrayIntoIterator<T, A>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.deque.as_slice() == other.deque.as_slice()
}
}
impl<T, A: FixedSizeArray<T>> Eq for ArrayIntoIterator<T, A> where T: Eq {}
impl<T, A: FixedSizeArray<T>> Clone for ArrayIntoIterator<T, A>
where
T: Clone,
{
fn clone(&self) -> Self {
ArrayIntoIterator {
deque: self.deque.clone(),
}
}
}
impl<T, A: FixedSizeArray<T>> Debug for ArrayIntoIterator<T, A>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ArrayIntoIterator")
.field("deque", &self.deque)
.finish()
}
}
impl<T, A: FixedSizeArray<T>> ArrayIntoIterator<T, A> {
pub fn new(array: A) -> ArrayIntoIterator<T, A> {
ArrayIntoIterator {
deque: FixedCapacityDequeLike::from_array(array),
}
}
}
impl<T, A: FixedSizeArray<T>> Iterator for ArrayIntoIterator<T, A> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.deque.pop_front()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.deque.length(), Some(self.deque.length()))
}
fn count(self) -> usize {
self.deque.length()
}
fn last(mut self) -> Option<T> {
self.deque.pop_back()
}
fn nth(&mut self, mut nth: usize) -> Option<T> {
while nth > 0 {
mem::drop(self.deque.pop_front());
nth -= 1;
}
self.deque.pop_front()
}
}
impl<T, A: FixedSizeArray<T>> DoubleEndedIterator for ArrayIntoIterator<T, A> {
fn next_back(&mut self) -> Option<T> {
self.deque.pop_back()
}
}
pub enum ArrayChunk<T, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> {
Chunk(CHUNK, PhantomData<T>),
Stump(STUMP, PhantomData<T>),
}
impl<T, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Debug for ArrayChunk<T, CHUNK, STUMP>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ArrayChunk::Chunk(chunk, pd) => f
.debug_tuple("Chunk")
.field(&chunk.as_slice())
.field(&pd)
.finish(),
ArrayChunk::Stump(stump, pd) => f
.debug_tuple("Stump")
.field(&stump.as_slice())
.field(&pd)
.finish(),
}
}
}
impl<T, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> PartialEq
for ArrayChunk<T, CHUNK, STUMP>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(ArrayChunk::Chunk(chunk, _), ArrayChunk::Chunk(other_chunk, _))
if chunk.as_slice() == other_chunk.as_slice() =>
{
true
}
(ArrayChunk::Stump(stump, _), ArrayChunk::Stump(other_stump, _))
if stump.as_slice() == other_stump.as_slice() =>
{
true
}
_ => false,
}
}
}
impl<T, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Eq for ArrayChunk<T, CHUNK, STUMP> where
T: Eq
{
}
impl<T, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Clone for ArrayChunk<T, CHUNK, STUMP>
where
T: Clone,
{
fn clone(&self) -> Self {
match self {
ArrayChunk::Chunk(chunk, _) => {
let chunk_clone: CHUNK =
try_init_from_iterator(chunk.as_slice().iter().cloned()).unwrap();
ArrayChunk::Chunk(chunk_clone, PhantomData)
}
ArrayChunk::Stump(stump, _) => {
let stump_clone: STUMP =
try_init_from_iterator(stump.as_slice().iter().cloned()).unwrap();
ArrayChunk::Stump(stump_clone, PhantomData)
}
}
}
}
pub struct ArrayChunks<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>>
{
iter: ArrayIntoIterator<T, A>,
has_stump: bool,
_chunk_pd: PhantomData<CHUNK>,
_stump_pd: PhantomData<STUMP>,
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Debug
for ArrayChunks<T, A, CHUNK, STUMP>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ArrayChunks")
.field("iter", &self.iter)
.field("has_stump", &self.has_stump)
.field("_chunk_pd", &self._chunk_pd)
.field("_stump_pd", &self._stump_pd)
.finish()
}
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> PartialEq
for ArrayChunks<T, A, CHUNK, STUMP>
where
T: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.iter == other.iter && self.has_stump == other.has_stump
}
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Eq
for ArrayChunks<T, A, CHUNK, STUMP>
where
T: Eq,
{
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Clone
for ArrayChunks<T, A, CHUNK, STUMP>
where
T: Clone,
{
fn clone(&self) -> Self {
ArrayChunks {
iter: self.iter.clone(),
has_stump: self.has_stump,
_chunk_pd: PhantomData,
_stump_pd: PhantomData,
}
}
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>>
ArrayChunks<T, A, CHUNK, STUMP>
{
pub fn new(array: A) -> ArrayChunks<T, A, CHUNK, STUMP> {
let chunk_length = length_of::<T, CHUNK>();
assert_ne!(chunk_length, 0);
let array_length = length_of::<T, A>();
let stump_length = length_of::<T, STUMP>();
assert_eq!(
array_length % chunk_length,
stump_length,
"Invalid stump length, expected {}.",
stump_length
);
let iter = ArrayIntoIterator::new(array);
let (elements_remain, _) = iter.size_hint();
let has_stump = elements_remain % length_of::<T, CHUNK>() > 0;
ArrayChunks {
iter,
has_stump,
_chunk_pd: PhantomData,
_stump_pd: PhantomData,
}
}
fn items_remain(&self) -> usize {
let (elements_remain, _) = self.iter.size_hint();
if self.has_stump {
elements_remain / length_of::<T, CHUNK>() + 1
} else {
elements_remain / length_of::<T, CHUNK>()
}
}
fn has_chunks(&self) -> bool {
let (elements_remain, _) = self.iter.size_hint();
elements_remain / length_of::<T, CHUNK>() > 0
}
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>> Iterator
for ArrayChunks<T, A, CHUNK, STUMP>
{
type Item = ArrayChunk<T, CHUNK, STUMP>;
fn next(&mut self) -> Option<Self::Item> {
if self.has_chunks() {
let chunk: CHUNK = try_init_from_iterator(self.iter.by_ref()).unwrap();
Some(ArrayChunk::Chunk(chunk, PhantomData))
} else if self.has_stump {
let stump: STUMP = try_init_from_iterator(self.iter.by_ref()).unwrap();
self.has_stump = false;
Some(ArrayChunk::Stump(stump, PhantomData))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.items_remain(), Some(self.items_remain()))
}
fn count(self) -> usize {
self.items_remain()
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
fn nth(&mut self, mut nth: usize) -> Option<Self::Item> {
while nth > 0 {
mem::drop(self.next());
nth -= 1;
}
self.next()
}
}
impl<T, A: FixedSizeArray<T>, CHUNK: FixedSizeArray<T>, STUMP: FixedSizeArray<T>>
DoubleEndedIterator for ArrayChunks<T, A, CHUNK, STUMP>
{
fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
if self.has_stump {
let mut stump: STUMP = try_init_from_iterator(self.iter.by_ref().rev()).unwrap();
stump.as_mut_slice().reverse();
self.has_stump = false;
Some(ArrayChunk::Stump(stump, PhantomData))
} else if self.has_chunks() {
let mut chunk: CHUNK = try_init_from_iterator(self.iter.by_ref().rev()).unwrap();
chunk.as_mut_slice().reverse();
Some(ArrayChunk::Chunk(chunk, PhantomData))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn not_enough_items() {
let maybe_array: Option<[u64; 5]> = super::try_init_from_iterator(1..=4);
assert_eq!(maybe_array, None);
}
#[test]
fn exact_item_count() {
let maybe_array: Option<[u64; 5]> = super::try_init_from_iterator(1..=5);
assert_eq!(maybe_array, Some([1, 2, 3, 4, 5]));
}
#[test]
fn too_many_items() {
let maybe_array: Option<[u32; 5]> = super::try_init_from_iterator(1..=100);
assert_eq!(maybe_array, Some([1, 2, 3, 4, 5]));
}
#[test]
fn array_into_iterator() {
let mut iter = super::ArrayIntoIterator::new([1, 2, 3, 4, 5]);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(5));
assert_eq!(iter.next(), None);
}
#[test]
fn array_into_iterator_reverse() {
let mut iter = super::ArrayIntoIterator::new([1, 2, 3, 4, 5]).rev();
assert_eq!(iter.next(), Some(5));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), None);
}
#[test]
fn array_into_iterator_take_from_two_sides() {
let mut iter = super::ArrayIntoIterator::new([1, 2, 3, 4, 5]);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next_back(), Some(5));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next_back(), Some(4));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
}
#[test]
fn array_into_iterator_next() {
let array = [1, 2, 3, 4, 5, 6, 7];
let mut iter = super::ArrayIntoIterator::new(array);
assert_eq!(iter.next(), Some(1));
}
#[test]
fn array_into_iterator_size_hint() {
let array = [1, 2, 3, 4, 5, 6, 7];
let mut iter = super::ArrayIntoIterator::new(array);
assert_eq!(iter.size_hint(), (7, Some(7)));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.size_hint(), (6, Some(6)));
}
#[test]
fn array_into_iterator_count() {
let array = [1, 2, 3, 4, 5, 6, 7];
let iter = super::ArrayIntoIterator::new(array);
assert_eq!(iter.count(), 7);
}
#[test]
fn array_into_iterator_last() {
let array = [1, 2, 3, 4, 5, 6, 7];
let iter = super::ArrayIntoIterator::new(array);
assert_eq!(iter.last(), Some(7));
}
#[test]
fn array_into_iterator_nth() {
let array = [1, 2, 3, 4, 5, 6, 7];
let mut iter = super::ArrayIntoIterator::new(array);
assert_eq!(iter.nth(5), Some(6));
}
#[test]
fn init_with_fn() {
fn initializer() -> u64 {
7
}
let array: [u64; 7] = super::init_with(initializer);
assert_eq!(array, [7, 7, 7, 7, 7, 7, 7]);
}
#[test]
fn init_with_closure() {
let mut value = 0;
let array: [u64; 7] = super::init_with(|| {
let return_value = value;
value += 1;
return return_value;
});
assert_eq!(array, [0, 1, 2, 3, 4, 5, 6]);
}
#[test]
fn indexed_init_with_fn() {
fn initializer(idx: usize) -> u64 {
(idx % 2) as u64
}
let array: [u64; 7] = super::indexed_init_with(initializer);
assert_eq!(array, [0, 1, 0, 1, 0, 1, 0]);
}
#[test]
fn indexed_init_with_closure() {
let array: [u64; 7] = super::indexed_init_with(|idx| (idx % 2) as u64);
assert_eq!(array, [0, 1, 0, 1, 0, 1, 0]);
}
#[test]
fn length_of_empty() {
let length = super::length_of::<Option<u64>, [Option<u64>; 0]>();
assert_eq!(length, 0);
}
#[test]
fn length_of_non_empty() {
let length = super::length_of::<Option<u64>, [Option<u64>; 7]>();
assert_eq!(length, 7);
}
#[test]
fn split_okay() {
let array: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let (left, right): ([u64; 2], [u64; 6]) = super::split(array);
assert_eq!(left, [1, 2]);
assert_eq!(right, [3, 4, 5, 6, 7, 8]);
}
#[test]
fn split_okay_empty_left() {
let array: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let (left, right): ([u64; 0], [u64; 8]) = super::split(array);
assert_eq!(left, []);
assert_eq!(right, [1, 2, 3, 4, 5, 6, 7, 8]);
}
#[test]
fn split_okay_empty_right() {
let array: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let (left, right): ([u64; 8], [u64; 0]) = super::split(array);
assert_eq!(left, [1, 2, 3, 4, 5, 6, 7, 8]);
assert_eq!(right, []);
}
#[test]
#[should_panic]
fn split_split_invalid_lengths_sum() {
let array: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
let (_left, _right): ([u64; 2], [u64; 4]) = super::split(array);
}
#[test]
fn split_empty_into_empty_and_empty() {
let array: [u64; 0] = [];
let (_left, _right): ([u64; 0], [u64; 0]) = super::split(array);
}
#[test]
fn join_okay() {
let left: [u64; 2] = [1, 2];
let right: [u64; 6] = [3, 4, 5, 6, 7, 8];
let joined: [u64; 8] = super::join(left, right);
assert_eq!(joined, [1u64, 2, 3, 4, 5, 6, 7, 8]);
}
#[test]
fn join_empty_and_empty() {
let left: [u64; 0] = [];
let right: [u64; 0] = [];
let joined: [u64; 0] = super::join(left, right);
assert_eq!(joined, []);
}
#[test]
fn join_okay_empty_left() {
let left: [u64; 0] = [];
let right: [u64; 6] = [1, 2, 3, 4, 5, 6];
let joined: [u64; 6] = super::join(left, right);
assert_eq!(joined, [1u64, 2, 3, 4, 5, 6]);
}
#[test]
fn join_okay_empty_right() {
let left: [u64; 6] = [1, 2, 3, 4, 5, 6];
let right: [u64; 0] = [];
let joined: [u64; 6] = super::join(left, right);
assert_eq!(joined, [1u64, 2, 3, 4, 5, 6]);
}
#[test]
#[should_panic]
fn join_insufficient_capacity() {
let left: [u64; 2] = [1, 2];
let right: [u64; 5] = [3, 4, 5, 6, 7];
let _joined: [u64; 6] = super::join(left, right);
}
#[test]
#[should_panic]
fn join_excessive_capacity() {
let left: [u64; 2] = [1, 2];
let right: [u64; 5] = [3, 4, 5, 6, 7];
let _joined: [u64; 10] = super::join(left, right);
}
#[test]
fn array_chunks_with_stump() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 8] = [1u64, 2, 3, 4, 5, 6, 7, 8];
let mut chunks: ArrayChunks<u64, [u64; 8], [u64; 3], [u64; 2]> = ArrayChunks::new(array);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2, 3], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([4u64, 5, 6], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Stump([7u64, 8], PhantomData))
);
assert_eq!(chunks.next(), None);
}
#[test]
fn array_chunks_without_stump() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let mut chunks: ArrayChunks<u64, [u64; 9], [u64; 3], [u64; 0]> = ArrayChunks::new(array);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2, 3], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([4u64, 5, 6], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([7u64, 8, 9], PhantomData))
);
assert_eq!(chunks.next(), None);
}
#[test]
fn array_chunks_with_stump_rev() {
use super::{ArrayChunk, ArrayChunks};
use core::iter::Rev;
use core::marker::PhantomData;
let array: [u64; 8] = [1u64, 2, 3, 4, 5, 6, 7, 8];
let mut chunks: Rev<ArrayChunks<u64, [u64; 8], [u64; 3], [u64; 2]>> =
ArrayChunks::new(array).rev();
assert_eq!(
chunks.next(),
Some(ArrayChunk::Stump([7u64, 8], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([4u64, 5, 6], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2, 3], PhantomData))
);
assert_eq!(chunks.next(), None);
}
#[test]
fn array_chunks_withot_stump_rev() {
use super::{ArrayChunk, ArrayChunks};
use core::iter::Rev;
use core::marker::PhantomData;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let mut chunks: Rev<ArrayChunks<u64, [u64; 9], [u64; 3], [u64; 0]>> =
ArrayChunks::new(array).rev();
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([7u64, 8, 9], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([4u64, 5, 6], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2, 3], PhantomData))
);
assert_eq!(chunks.next(), None);
}
#[test]
fn array_chunks_with_stump_take_from_two_sides_front_first() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let mut chunks: ArrayChunks<u64, [u64; 9], [u64; 2], [u64; 1]> = ArrayChunks::new(array);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2], PhantomData))
);
assert_eq!(
chunks.next_back(),
Some(ArrayChunk::Stump([9u64], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([3u64, 4], PhantomData))
);
assert_eq!(
chunks.next_back(),
Some(ArrayChunk::Chunk([7u64, 8], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([5u64, 6], PhantomData))
);
assert_eq!(chunks.next_back(), None);
assert_eq!(chunks.next(), None);
}
#[test]
fn array_chunks_with_stump_take_from_two_sides_back_first() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let mut chunks: ArrayChunks<u64, [u64; 9], [u64; 2], [u64; 1]> = ArrayChunks::new(array);
assert_eq!(
chunks.next_back(),
Some(ArrayChunk::Stump([9u64], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([1u64, 2], PhantomData))
);
assert_eq!(
chunks.next_back(),
Some(ArrayChunk::Chunk([7u64, 8], PhantomData))
);
assert_eq!(
chunks.next(),
Some(ArrayChunk::Chunk([3u64, 4], PhantomData))
);
assert_eq!(
chunks.next_back(),
Some(ArrayChunk::Chunk([5u64, 6], PhantomData))
);
assert_eq!(chunks.next(), None);
assert_eq!(chunks.next_back(), None);
}
#[test]
fn array_chunks_with_stump_size_hint() {
use super::ArrayChunks;
let array: [u64; 8] = [1u64, 2, 3, 4, 5, 6, 7, 8];
let chunks: ArrayChunks<u64, [u64; 8], [u64; 3], [u64; 2]> = ArrayChunks::new(array);
assert_eq!(chunks.size_hint(), (3, Some(3)));
}
#[test]
fn array_chunks_without_stump_size_hint() {
use super::ArrayChunks;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let chunks: ArrayChunks<u64, [u64; 9], [u64; 3], [u64; 0]> = ArrayChunks::new(array);
assert_eq!(chunks.size_hint(), (3, Some(3)));
}
#[test]
fn array_chunks_with_stump_count() {
use super::ArrayChunks;
let array: [u64; 8] = [1u64, 2, 3, 4, 5, 6, 7, 8];
let chunks: ArrayChunks<u64, [u64; 8], [u64; 3], [u64; 2]> = ArrayChunks::new(array);
assert_eq!(chunks.count(), 3);
}
#[test]
fn array_chunks_without_stump_count() {
use super::ArrayChunks;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let chunks: ArrayChunks<u64, [u64; 9], [u64; 3], [u64; 0]> = ArrayChunks::new(array);
assert_eq!(chunks.count(), 3);
}
#[test]
fn array_chunks_with_stump_last() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 8] = [1u64, 2, 3, 4, 5, 6, 7, 8];
let chunks: ArrayChunks<u64, [u64; 8], [u64; 3], [u64; 2]> = ArrayChunks::new(array);
assert_eq!(
chunks.last(),
Some(ArrayChunk::Stump([7u64, 8], PhantomData))
);
}
#[test]
fn array_chunks_without_stump_last() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 9] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9];
let chunks: ArrayChunks<u64, [u64; 9], [u64; 3], [u64; 0]> = ArrayChunks::new(array);
assert_eq!(
chunks.last(),
Some(ArrayChunk::Chunk([7u64, 8, 9], PhantomData))
);
}
#[test]
fn array_chunks_nth() {
use super::{ArrayChunk, ArrayChunks};
use core::marker::PhantomData;
let array: [u64; 17] = [1u64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17];
let mut chunks: ArrayChunks<u64, [u64; 17], [u64; 2], [u64; 1]> = ArrayChunks::new(array);
assert_eq!(
chunks.nth(5),
Some(ArrayChunk::Chunk([11u64, 12], PhantomData))
);
}
#[test]
fn fixed_capacity_deque_like_eq() {
use super::FixedCapacityDequeLike;
let mut deque1: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque1.push_back(1);
deque1.push_back(2);
deque1.push_back(3);
deque1.push_back(4);
deque1.push_back(5);
deque1.pop_front();
deque1.pop_front();
let mut deque2: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque2.push_back(1);
deque2.push_back(2);
deque2.push_back(3);
deque2.push_back(4);
deque2.push_back(5);
deque2.pop_front();
deque2.pop_front();
assert_eq!(deque1, deque2);
}
#[test]
fn fixed_capacity_deque_like_eq_empty() {
use super::FixedCapacityDequeLike;
let deque1: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
let deque2: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
assert_eq!(deque1, deque2);
}
#[test]
fn fixed_capacity_deque_like_not_eq_different_items() {
use super::FixedCapacityDequeLike;
let mut deque1: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque1.push_back(1);
deque1.push_back(2);
let mut deque2: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque2.push_back(2);
deque1.push_back(3);
assert_ne!(deque1, deque2);
}
#[test]
fn fixed_capacity_deque_like_not_eq_different_offsets() {
use super::FixedCapacityDequeLike;
let mut deque1: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque1.push_back(0);
deque1.push_back(1);
deque1.push_back(2);
deque1.pop_back();
let mut deque2: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque2.push_back(1);
deque1.push_back(2);
assert_ne!(deque1, deque2);
}
#[test]
fn fixed_capacity_deque_like_clone_no_offset() {
use super::FixedCapacityDequeLike;
let mut deque: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque.push_back(1);
deque.push_back(2);
deque.push_back(3);
let clone = deque.clone();
assert_eq!(deque, clone);
}
#[test]
fn fixed_capacity_deque_like_clone_with_offset() {
use super::FixedCapacityDequeLike;
let mut deque: FixedCapacityDequeLike<u64, [u64; 10]> = FixedCapacityDequeLike::new();
deque.push_back(1);
deque.push_back(2);
deque.push_back(3);
deque.push_back(4);
deque.push_back(5);
deque.pop_back();
deque.pop_front();
let clone = deque.clone();
assert_eq!(deque, clone);
}
#[test]
fn array_into_iterator_eq() {
use super::ArrayIntoIterator;
let a = [1, 2, 3, 4, 5];
let b = [1, 2, 3, 4, 5];
let iter_a = ArrayIntoIterator::new(a);
let iter_b = ArrayIntoIterator::new(b);
assert_eq!(iter_a, iter_b);
}
#[test]
fn array_into_iterator_eq_if_items_eq() {
use super::ArrayIntoIterator;
use core::mem;
let a = [1, 2, 3, 4, 5, 6];
let b = [0, 0, 0, 3, 4, 5];
let mut iter_a = ArrayIntoIterator::new(a);
let mut iter_b = ArrayIntoIterator::new(b);
mem::drop(iter_a.next());
mem::drop(iter_a.next());
mem::drop(iter_a.next_back());
mem::drop(iter_b.next());
mem::drop(iter_b.next());
mem::drop(iter_b.next());
assert_eq!(iter_a, iter_b);
}
#[test]
fn array_into_iterator_clone() {
use super::ArrayIntoIterator;
let a = [1, 2, 3, 4, 5];
let a_iter = ArrayIntoIterator::new(a);
let a_iter_clone = a_iter.clone();
assert_eq!(a_iter, a_iter_clone);
}
#[test]
fn array_chunk_eq_chunk() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk1: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([1, 2, 3, 4], PhantomData);
let chunk2: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([1, 2, 3, 4], PhantomData);
assert_eq!(chunk1, chunk2);
}
#[test]
fn array_chunk_eq_stump() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk1: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([1, 2, 3], PhantomData);
let chunk2: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([1, 2, 3], PhantomData);
assert_eq!(chunk1, chunk2);
}
#[test]
fn array_chunk_ne_stump_and_chunk() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk1: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([1, 2, 3, 4], PhantomData);
let chunk2: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([1, 2, 3], PhantomData);
assert_ne!(chunk1, chunk2);
}
#[test]
fn array_chunk_ne_different_chunk_items() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk1: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([1, 2, 3, 4], PhantomData);
let chunk2: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([4, 3, 2, 1], PhantomData);
assert_ne!(chunk1, chunk2);
}
#[test]
fn array_chunk_ne_different_stump_items() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk1: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([1, 2, 3], PhantomData);
let chunk2: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([4, 3, 2], PhantomData);
assert_ne!(chunk1, chunk2);
}
#[test]
fn array_chunk_clone_chunk() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk: ArrayChunk<u64, [u64; 4], [u64; 3]> =
ArrayChunk::Chunk([1, 2, 3, 4], PhantomData);
let chunk_clone = chunk.clone();
assert_eq!(chunk, chunk_clone);
}
#[test]
fn array_chunk_clone_stump() {
use super::ArrayChunk;
use core::marker::PhantomData;
let chunk: ArrayChunk<u64, [u64; 4], [u64; 3]> = ArrayChunk::Stump([1, 2, 3], PhantomData);
let chunk_clone = chunk.clone();
assert_eq!(chunk, chunk_clone);
}
#[test]
fn array_chunks_eq_case_1() {
use super::ArrayChunks;
use core::mem;
let a = [1, 2, 3, 4, 5, 6, 7, 8];
let mut a_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(a);
let b = [1, 2, 3, 4, 5, 6, 7, 8];
let mut b_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(b);
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next_back());
mem::drop(b_chunks.next_back());
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
}
#[test]
fn array_chunks_eq_case_2() {
use super::ArrayChunks;
use core::mem;
let a = [0, 1, 2, 4, 5, 6, 8, 9];
let mut a_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(a);
let b = [1, 2, 3, 4, 5, 6, 7, 8];
let mut b_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(b);
assert_ne!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_ne!(a_chunks, b_chunks);
mem::drop(a_chunks.next_back());
mem::drop(b_chunks.next_back());
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
}
#[test]
fn array_chunks_eq_case_3() {
use super::ArrayChunks;
use core::mem;
let a = [0, 1, 2, 4, 5, 6, 8, 9];
let mut a_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(a);
let b = [10, 11, 12, 13, 14, 15, 16, 17];
let mut b_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(b);
assert_ne!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_ne!(a_chunks, b_chunks);
mem::drop(a_chunks.next_back());
mem::drop(b_chunks.next_back());
assert_ne!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
}
#[test]
fn array_chunks_clone() {
use super::ArrayChunks;
use core::mem;
let a = [1, 2, 3, 4, 5, 6, 7, 8];
let mut a_chunks = ArrayChunks::<u64, [u64; 8], [u64; 3], [u64; 2]>::new(a);
let mut b_chunks = a_chunks.clone();
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next_back());
mem::drop(b_chunks.next_back());
assert_eq!(a_chunks, b_chunks);
mem::drop(a_chunks.next());
mem::drop(b_chunks.next());
assert_eq!(a_chunks, b_chunks);
}
#[test]
fn array_chunks_ommit_generic_parameters() {
use super::ArrayChunks;
let array = [1, 2, 3, 4, 5, 6, 7, 8];
let _chunks: ArrayChunks<_, _, [_; 3], [_; 2]> = ArrayChunks::new(array);
}
}