use std::fmt::{self, Display};
use std::iter::{ExactSizeIterator, FusedIterator};
use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut};
use std::slice;
pub struct ArrayVec<T, const CAPACITY: usize> {
items: [MaybeUninit<T>; CAPACITY],
size: usize,
}
impl<T, const CAPACITY: usize> ArrayVec<T, CAPACITY> {
pub fn new() -> Self {
let items: [MaybeUninit<T>; CAPACITY] = unsafe {
MaybeUninit::uninit().assume_init()
};
let size = 0;
Self { items, size }
}
pub const fn len(&self) -> usize {
self.size
}
pub unsafe fn set_len(&mut self, new_size: usize) {
self.size = new_size;
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
pub const fn is_full(&self) -> bool {
self.len() == CAPACITY
}
pub const fn capacity(&self) -> usize {
CAPACITY
}
pub fn push(&mut self, item: T) {
if !self.is_full() {
let size = self.size;
unsafe {
self.items[size].as_mut_ptr().write(item);
}
self.size += 1;
} else {
panic!("exceeded max capacity of ArrayVec");
}
}
pub fn pop(&mut self) -> Option<T> {
if !self.is_empty() {
self.size -= 1;
let size = self.size;
unsafe {
Some(
self.items[size].as_ptr().read(),
)
}
} else {
None
}
}
pub fn clear(&mut self) {
while !self.is_empty() {
self.pop();
}
}
pub fn as_slice<'a>(&'a self) -> &'a [T] {
unsafe {
let valid_ptr: *const T = {
let uninit_ptr: *const MaybeUninit<T> = self.items.as_ptr();
uninit_ptr.cast()
};
slice::from_raw_parts(valid_ptr, self.size)
}
}
pub fn as_slice_mut<'a>(&'a mut self) -> &'a mut [T] {
unsafe {
let valid_ptr: *mut T = {
let uninit_ptr: *mut MaybeUninit<T> = self.items.as_mut_ptr();
uninit_ptr.cast()
};
slice::from_raw_parts_mut(valid_ptr, self.size)
}
}
}
impl<T, const CAPACITY: usize> Drop for ArrayVec<T, CAPACITY> {
fn drop(&mut self) {
self.clear();
}
}
impl<T, const CAPACITY: usize> Deref for ArrayVec<T, CAPACITY> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, const CAPACITY: usize> DerefMut for ArrayVec<T, CAPACITY> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}
impl<T, const CAPACITY: usize> AsRef<[T]> for ArrayVec<T, CAPACITY> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, const CAPACITY: usize> AsMut<[T]> for ArrayVec<T, CAPACITY> {
fn as_mut(&mut self) -> &mut [T] {
self.as_slice_mut()
}
}
impl<T: Copy + Clone, const CAPACITY: usize> Clone for ArrayVec<T, CAPACITY> {
fn clone(&self) -> Self {
Self {
items: self.items.clone(),
size: self.size.clone(),
}
}
}
impl<T: Display, const CAPACITY: usize> Display for ArrayVec<T, CAPACITY> {
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, const CAPACITY: usize> IntoIterator for ArrayVec<T, CAPACITY> {
type Item = T;
type IntoIter = IntoIter<T, CAPACITY>;
fn into_iter(self) -> Self::IntoIter {
IntoIter::new(self)
}
}
impl<'a, T, const CAPACITY: usize> IntoIterator for &'a ArrayVec<T, CAPACITY> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice().iter()
}
}
impl<'a, T, const CAPACITY: usize> IntoIterator for &'a mut ArrayVec<T, CAPACITY> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.as_slice_mut().iter_mut()
}
}
pub struct IntoIter<T, const CAPACITY: usize> {
vec: ArrayVec<T, CAPACITY>,
size: usize,
idx: usize,
}
impl<T, const CAPACITY: usize> IntoIter<T, CAPACITY> {
fn new(array_vec: ArrayVec<T, CAPACITY>) -> Self {
todo!();
let size = array_vec.size;
unsafe {
array_vec.set_len(0);
}
Self {
vec: array_vec,
size,
idx: 0,
}
}
}
impl<T, const CAPACITY: usize> Iterator for IntoIter<T, CAPACITY> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.size, Some(self.size))
}
}
impl<T, const CAPACITY: usize> ExactSizeIterator for IntoIter<T, CAPACITY> {}
impl<T, const CAPACITY: usize> FusedIterator for IntoIter<T, CAPACITY> {}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[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]
fn deref_t_slice() {
let mut vec: ArrayVec<u32, 10> = ArrayVec::new();
assert_eq!(vec.contains(&500), false);
vec.push(500);
assert_eq!(vec.contains(&500), true);
assert_eq!(vec.get(0), Some(&500));
assert_eq!(vec.get(1), None);
*vec.get_mut(0).unwrap() = 10;
assert_eq!(vec.contains(&500), false);
assert_eq!(vec.contains(&10), true);
assert_eq!(vec.get(0), Some(&10));
assert_eq!(vec.get(1), None);
assert_eq!(vec.pop(), Some(10));
let mut items = HashSet::new();
items.insert(100);
items.insert(200);
items.insert(300);
let mut vec: ArrayVec<u32, 10> = ArrayVec::new();
for item in &items {
vec.push(*item);
}
for item in &vec {
assert!(items.contains(item));
}
}
#[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.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();
assert_eq!(arrayvec.len(), 0);
arrayvec.push(100);
arrayvec.push(500);
assert_eq!(arrayvec.len(), 2);
arrayvec.clear();
assert_eq!(arrayvec.len(), 0);
assert_eq!(arrayvec.pop(), None);
}
}