#![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
}
}
}
impl<T, A: FixedSizeArray<T>> Drop for FixedCapacityDequeLike<T, A> {
fn drop(&mut self) {
while let Some(item) = self.pop_back() {
mem::drop(item);
}
}
}
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 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>> 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
{
}
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>>
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))
);
}
}