machine_check/types/
array.rs

1use std::ops::{Index, IndexMut};
2
3use mck::{
4    concr::{IntoMck, UnsignedBitvector},
5    misc::LightArray,
6};
7
8use crate::Bitvector;
9
10///
11/// Power-of-two array of bitvectors without signedness information.
12///
13/// The exponent of array size is specified in the first generic parameter I.
14/// Element length is specified in the second generic parameter L.
15///
16/// The array is indexed by bitvectors of length I, so no out-of-bound access can occur.
17///
18#[derive(Debug, Clone, Hash, PartialEq, Eq)]
19pub struct BitvectorArray<const I: u32, const L: u32> {
20    pub(super) inner: LightArray<UnsignedBitvector<I>, Bitvector<L>>,
21}
22
23impl<const I: u32, const L: u32> BitvectorArray<I, L> {
24    /// Creates a new array filled with the given element.
25    pub fn new_filled(element: Bitvector<L>) -> Self {
26        Self {
27            inner: LightArray::new_filled(element),
28        }
29    }
30
31    /// Creates the bitvector array from a correctly sized slice of bitvectors.
32    ///
33    /// Panics if the bitvector slice length is not equal to 2<sup>L</sup>.
34    ///
35    /// Cannot be used within the machine_description macro.
36    pub fn from_slice(slice: &[Bitvector<L>]) -> Self {
37        assert!(I < usize::BITS);
38        assert_eq!(1 << I, slice.len());
39        // make zeroed first
40        let mut inner = LightArray::new_filled(Bitvector::new(0));
41        // assign each element
42        let mut index = UnsignedBitvector::zero();
43        for element in slice.iter().cloned() {
44            inner.write(index, element);
45            index = index + UnsignedBitvector::one();
46        }
47
48        Self { inner }
49    }
50}
51
52impl<const I: u32, const L: u32> Index<Bitvector<I>> for BitvectorArray<I, L> {
53    type Output = Bitvector<L>;
54
55    fn index(&self, index: Bitvector<I>) -> &Self::Output {
56        &self.inner[index.into_mck().cast_unsigned()]
57    }
58}
59
60impl<const I: u32, const L: u32> IndexMut<Bitvector<I>> for BitvectorArray<I, L> {
61    fn index_mut(&mut self, index: Bitvector<I>) -> &mut Self::Output {
62        self.inner.mutable_index(index.into_mck().cast_unsigned())
63    }
64}
65
66impl<const I: u32, const L: u32> IntoMck for BitvectorArray<I, L> {
67    type Type = mck::concr::Array<I, L>;
68
69    fn into_mck(self) -> Self::Type {
70        Self::Type::from_inner(self.inner.map(|v| v.into_mck()))
71    }
72}