use std::array;
use std::cmp::Ordering;
use std::fmt::{self, Display};
use std::iter::{ExactSizeIterator, FusedIterator};
use std::mem;
use std::ops::{Index, IndexMut};
#[derive(Debug, Clone)]
pub struct ArrayVec<T: Clone, const CAPACITY: usize> {
items: [Option<T>; CAPACITY],
size: usize,
}
impl<T: Clone, const CAPACITY: usize> ArrayVec<T, CAPACITY> {
pub const CAP: usize = CAPACITY;
pub fn new() -> Self
where
T: Copy,
{
Self {
items: [None; CAPACITY],
size: 0,
}
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn is_full(&self) -> bool {
self.size == CAPACITY
}
pub fn contains(&self, item: &T) -> bool
where
T: PartialEq,
{
self.items[0..self.size]
.iter()
.any(|t| t.as_ref() == Some(item))
}
pub fn push(&mut self, item: T) {
if !self.is_full() {
self.items[self.size] = Some(item);
self.size += 1;
} else {
panic!("Exceeded max capacity of array.");
}
}
pub fn append(&mut self, other: ArrayVec<T, CAPACITY>) {
for item in other {
self.push(item);
}
}
pub fn pop(&mut self) -> Option<T> {
if !self.is_empty() {
self.size -= 1;
mem::replace(&mut self.items[self.size], None)
} else {
None
}
}
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len() {
self.items[index].as_ref()
} else {
None
}
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len() {
self.items[index].as_mut()
} else {
None
}
}
pub fn clear(&mut self) {
for item in &mut self.items[0..self.size] {
*item = None;
}
self.size = 0;
}
pub fn sort_unstable_by<F>(&mut self, mut compare: F)
where
F: FnMut(&T, &T) -> Ordering,
{
let len = self.len();
self.items[0..len].sort_unstable_by(|left, right| {
compare(left.as_ref().unwrap(), right.as_ref().unwrap())
});
}
pub fn iter(&self) -> Iter<T, CAPACITY> {
Iter::<T, CAPACITY>::new(self)
}
}
impl<T: Clone, const CAPACITY: usize> Index<usize> for ArrayVec<T, CAPACITY> {
type Output = T;
fn index(&self, idx: usize) -> &Self::Output {
self.get(idx).unwrap()
}
}
impl<T: Clone, const CAPACITY: usize> IndexMut<usize> for ArrayVec<T, CAPACITY> {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
self.get_mut(idx).unwrap()
}
}
impl<T: Clone, const CAPACITY: usize> IntoIterator for ArrayVec<T, CAPACITY> {
type Item = T;
type IntoIter = IntoIter<T, CAPACITY>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::<T, CAPACITY>::new(self)
}
}
#[derive(Debug, Clone)]
pub struct IntoIter<T, const CAPACITY: usize> {
it: array::IntoIter<Option<T>, CAPACITY>,
size: usize,
}
impl<T: Clone, const CAPACITY: usize> IntoIter<T, CAPACITY> {
pub fn new(array_vec: ArrayVec<T, CAPACITY>) -> Self {
assert!(array_vec.size < CAPACITY);
let it = std::array::IntoIter::new(array_vec.items);
let size = array_vec.size;
Self { it, size }
}
}
impl<T: Clone, const CAPACITY: usize> Iterator for IntoIter<T, CAPACITY> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.size > 0 {
self.size -= 1;
self.it.next().unwrap()
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.size, Some(self.size))
}
}
impl<T: Clone, const CAPACITY: usize> ExactSizeIterator for IntoIter<T, CAPACITY> {}
impl<T: Clone, const CAPACITY: usize> FusedIterator for IntoIter<T, CAPACITY> {}
pub struct Iter<'a, T, const CAPACITY: usize> {
it: std::slice::Iter<'a, Option<T>>,
}
impl<'a, T: Clone, const CAPACITY: usize> Iter<'a, T, CAPACITY> {
fn new(arrayvec: &'a ArrayVec<T, CAPACITY>) -> Self {
let it = arrayvec.items[0..arrayvec.len()].iter();
Self { it }
}
}
impl<'a, T, const CAPACITY: usize> Iterator for Iter<'a, T, CAPACITY> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.it.next().map(|opt| opt.as_ref().unwrap())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
impl<'a, T, const CAPACITY: usize> ExactSizeIterator for Iter<'a, T, CAPACITY> {}
impl<'a, T, const CAPACITY: usize> FusedIterator for Iter<'a, T, CAPACITY> {}
impl<T, const CAPACITY: usize> Display for ArrayVec<T, CAPACITY>
where
T: Clone + Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut displayed = String::new();
for item in self.iter() {
displayed.push_str(&item.to_string());
displayed.push(' ');
}
displayed.pop();
f.write_str(&displayed)
}
}
impl<T: Clone + Copy, const CAPACITY: usize> Default for ArrayVec<T, CAPACITY> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn integer_push_pop() {
const CAP: usize = 10;
let mut arr_vec = ArrayVec::<i32, CAP>::new();
arr_vec.push(10);
assert_eq!(arr_vec.len(), 1);
assert!(!arr_vec.is_empty());
let item = arr_vec.pop();
assert_eq!(item.unwrap(), 10);
assert_eq!(arr_vec.len(), 0);
assert!(arr_vec.is_empty());
let item = arr_vec.pop();
assert!(item.is_none());
assert_eq!(arr_vec.len(), 0);
assert!(arr_vec.is_empty());
let item = arr_vec.pop();
assert!(item.is_none());
assert_eq!(arr_vec.len(), 0);
assert!(arr_vec.is_empty());
arr_vec.push(20);
assert_eq!(arr_vec.len(), 1);
assert!(!arr_vec.is_empty());
let item = arr_vec.pop();
assert_eq!(item.unwrap(), 20);
assert_eq!(arr_vec.len(), 0);
assert!(arr_vec.is_empty());
}
#[test]
#[should_panic]
fn panics_when_capacity_exceeded() {
const CAP: usize = 2;
let mut list = ArrayVec::<i32, CAP>::new();
list.push(100);
list.push(500);
assert_eq!(list.len(), 2);
assert!(!list.is_empty());
list.push(1000);
}
#[test]
fn sorting() {
let mut arrayvec = ArrayVec::<i32, 100>::new();
arrayvec.push(40);
arrayvec.push(300);
arrayvec.push(-10);
arrayvec.push(0);
assert_eq!(4, arrayvec.len());
arrayvec.sort_unstable_by(|a, b| a.cmp(b));
assert_eq!(4, arrayvec.len());
let mut iter = arrayvec.into_iter();
assert_eq!(-10, iter.next().unwrap());
assert_eq!(0, iter.next().unwrap());
assert_eq!(40, iter.next().unwrap());
assert_eq!(300, iter.next().unwrap());
assert_eq!(None, iter.next());
}
#[test]
fn clears() {
let mut arrayvec = ArrayVec::<i32, 100>::new();
for item in &arrayvec.items {
assert_eq!(*item, None);
}
arrayvec.push(100);
arrayvec.push(500);
assert_eq!(arrayvec.len(), 2);
arrayvec.clear();
assert_eq!(arrayvec.len(), 0);
for item in &arrayvec.items {
assert_eq!(*item, None);
}
}
}