ach_array/
lib.rs

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    /// pop a value from random position
37    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    /// push a value to random position, return index
46    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    /// It will ignore values which is transient if strict is `false`
57    /// Notice: `Spin` if strict
58    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}