1#![no_std]
2
3use ach_cell::Cell;
4pub use ach_cell::Ref;
5use core::ops::Index;
6
7pub struct Array<T, const N: usize> {
8 buf: [Cell<T>; N],
9}
10impl<T, const N: usize> Default for Array<T, N> {
11 fn default() -> Self {
12 Self::new()
13 }
14}
15impl<T, const N: usize> Array<T, N> {
16 const CAPACITY: usize = N;
17 #[allow(clippy::declare_interior_mutable_const)]
18 const INIT_ITEM: Cell<T> = Cell::new();
19 pub const fn new() -> Self {
20 Array {
21 buf: [Self::INIT_ITEM; N],
22 }
23 }
24 pub const fn capacity(&self) -> usize {
25 Self::CAPACITY
26 }
27 pub fn is_empty(&self) -> bool {
28 self.buf.iter().all(|x| !x.is_initialized())
29 }
30 pub fn is_full(&self) -> bool {
31 self.buf.iter().all(|x| x.is_initialized())
32 }
33 pub fn clear(&mut self) {
34 self.buf = [Self::INIT_ITEM; N];
35 }
36 pub fn pop(&self) -> Option<T> {
38 for index in 0..self.capacity() {
39 if let Ok(Some(x)) = self.buf[index].try_take() {
40 return Some(x);
41 }
42 }
43 None
44 }
45 pub fn push(&self, mut value: T) -> Result<usize, T> {
47 for index in 0..self.capacity() {
48 if let Err(v) = self.buf[index].try_set(value) {
49 value = v.input;
50 } else {
51 return Ok(index);
52 }
53 }
54 Err(value)
55 }
56 pub fn iter(&self, strict: bool) -> ArrayIterator<'_, T, N> {
59 ArrayIterator {
60 vec: self,
61 index: 0,
62 strict,
63 }
64 }
65}
66impl<T, const N: usize> Index<usize> for Array<T, N> {
67 type Output = Cell<T>;
68 fn index(&self, index: usize) -> &Self::Output {
69 &self.buf[index]
70 }
71}
72
73pub struct ArrayIterator<'a, T, const N: usize> {
74 vec: &'a Array<T, N>,
75 index: usize,
76 strict: bool,
77}
78impl<'a, T, const N: usize> Iterator for ArrayIterator<'a, T, N> {
79 type Item = Ref<'a, T>;
80 fn next(&mut self) -> Option<Self::Item> {
81 if self.index >= self.vec.capacity() {
82 return None;
83 }
84 let ret = if self.strict {
85 self.vec[self.index].get()
86 } else {
87 self.vec[self.index].try_get()
88 };
89 self.index += 1;
90 if let Ok(ret) = ret {
91 Some(ret)
92 } else {
93 self.next()
94 }
95 }
96}