hv1_structs/
vtl_array.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Container data structures indexable by [`Vtl`].
5
6use bitvec::array::BitArray;
7use core::ops::Deref;
8use core::ops::DerefMut;
9use core::ops::Index;
10use core::ops::IndexMut;
11use hvdef::Vtl;
12use inspect::Inspect;
13use inspect::InspectMut;
14
15// TODO: Enforce N <= 3 on the type when stable
16/// An array indexable by [`Vtl`].
17#[derive(Debug, Clone)]
18pub struct VtlArray<T, const N: usize> {
19    data: [T; N],
20}
21
22impl<T, const N: usize> VtlArray<T, N> {
23    /// Creates an array of type T, where each element is `value`.
24    pub const fn new(value: T) -> Self
25    where
26        T: Copy,
27    {
28        assert!(N > 0 && N <= 3);
29        Self { data: [value; N] }
30    }
31
32    /// Creates an array of type T, where each element is
33    /// the returned value from `f` using that element’s index.
34    pub fn from_fn<F>(mut f: F) -> Self
35    where
36        F: FnMut(Vtl) -> T,
37    {
38        assert!(N > 0 && N <= 3);
39        Self {
40            data: core::array::from_fn(|i| f(Vtl::try_from(i as u8).unwrap())),
41        }
42    }
43
44    /// Maps over the vtl array using the raw underlying array.
45    pub fn map<U, F>(self, f: F) -> VtlArray<U, N>
46    where
47        F: FnMut(T) -> U,
48    {
49        VtlArray {
50            data: self.data.map(f),
51        }
52    }
53
54    /// Borrows each element and returns an array of references with the same
55    /// size as self.
56    pub fn each_ref(&self) -> VtlArray<&T, N> {
57        VtlArray {
58            data: self.data.each_ref(),
59        }
60    }
61
62    /// Borrows each element mutably and returns an array of mutable references
63    /// with the same size as self.
64    pub fn each_mut(&mut self) -> VtlArray<&mut T, N> {
65        VtlArray {
66            data: self.data.each_mut(),
67        }
68    }
69
70    /// Returns the raw underlying array.
71    pub fn into_inner(self) -> [T; N] {
72        self.data
73    }
74}
75
76impl<T> From<[T; 1]> for VtlArray<T, 1> {
77    fn from(a: [T; 1]) -> Self {
78        Self { data: a }
79    }
80}
81
82impl<T> From<[T; 2]> for VtlArray<T, 2> {
83    fn from(a: [T; 2]) -> Self {
84        Self { data: a }
85    }
86}
87
88impl<T> From<[T; 3]> for VtlArray<T, 3> {
89    fn from(a: [T; 3]) -> Self {
90        Self { data: a }
91    }
92}
93
94// TODO: Remove this when deriving Default for arrays is stable
95impl<T, const N: usize> Default for VtlArray<T, N>
96where
97    T: Default,
98{
99    fn default() -> Self {
100        Self::from_fn(|_| T::default())
101    }
102}
103
104impl<T, const N: usize> Inspect for VtlArray<T, N>
105where
106    T: Inspect,
107{
108    fn inspect(&self, req: inspect::Request<'_>) {
109        inspect::iter_by_index(&self.data).inspect(req)
110    }
111}
112
113impl<T, const N: usize> InspectMut for VtlArray<T, N>
114where
115    T: InspectMut,
116{
117    fn inspect_mut(&mut self, req: inspect::Request<'_>) {
118        let mut resp = req.respond();
119        for (i, data) in self.data.iter_mut().enumerate() {
120            resp.field_mut(
121                match i {
122                    0 => "0",
123                    1 => "1",
124                    2 => "2",
125                    _ => unreachable!(),
126                },
127                data,
128            );
129        }
130    }
131}
132
133impl<T, V: Into<Vtl>, const N: usize> Index<V> for VtlArray<T, N> {
134    type Output = T;
135
136    fn index(&self, index: V) -> &Self::Output {
137        &self.data[index.into() as usize]
138    }
139}
140
141impl<T, V: Into<Vtl>, const N: usize> IndexMut<V> for VtlArray<T, N> {
142    fn index_mut(&mut self, index: V) -> &mut Self::Output {
143        &mut self.data[index.into() as usize]
144    }
145}
146
147impl<T, const N: usize> Deref for VtlArray<T, N> {
148    type Target = [T; N];
149
150    fn deref(&self) -> &Self::Target {
151        &self.data
152    }
153}
154
155impl<T, const N: usize> DerefMut for VtlArray<T, N> {
156    fn deref_mut(&mut self) -> &mut Self::Target {
157        &mut self.data
158    }
159}
160
161/// A set of [`Vtl`]s.
162#[derive(Copy, Clone)]
163pub struct VtlSet {
164    bits: BitArray<u16>,
165}
166
167impl VtlSet {
168    /// Creates a new empty set.
169    pub fn new() -> Self {
170        Self {
171            bits: BitArray::new(0),
172        }
173    }
174
175    /// Adds a [`Vtl`] to the set.
176    pub fn set(&mut self, vtl: Vtl) {
177        self.bits.set(vtl as usize, true);
178    }
179
180    /// Removes a [`Vtl`] from the set.
181    pub fn clear(&mut self, vtl: Vtl) {
182        self.bits.set(vtl as usize, false);
183    }
184
185    /// Returns true if any [`Vtl`] in the set is higher than `vtl`.
186    pub fn is_higher_vtl_set_than(&self, vtl: Vtl) -> bool {
187        self.highest_set() > Some(vtl)
188    }
189
190    /// Returns the highest set [`Vtl`] in the set, if any.
191    pub fn highest_set(&self) -> Option<Vtl> {
192        Some(Vtl::try_from(self.bits.last_one()? as u8).unwrap())
193    }
194
195    /// Returns true if the given [`Vtl`] is set.
196    pub fn is_set<V: Into<Vtl>>(&self, vtl: V) -> bool {
197        self.bits[vtl.into() as usize]
198    }
199
200    /// Returns true if the given [`Vtl`] is not set.
201    pub fn is_clear<V: Into<Vtl>>(&self, vtl: V) -> bool {
202        !self.is_set(vtl)
203    }
204
205    /// Returns an iterator over the set [`Vtl`]s, in order from highest to lowest.
206    pub fn iter_highest_first(&self) -> impl Iterator<Item = Vtl> + '_ {
207        self.bits
208            .iter_ones()
209            .rev()
210            .map(|i| Vtl::try_from(i as u8).unwrap())
211    }
212}
213
214impl Inspect for VtlSet {
215    fn inspect(&self, req: inspect::Request<'_>) {
216        inspect::iter_by_index(self.bits.iter().map(|v| *v)).inspect(req)
217    }
218}
219
220impl From<u16> for VtlSet {
221    fn from(bits: u16) -> Self {
222        VtlSet {
223            bits: BitArray::new(bits),
224        }
225    }
226}
227
228#[cfg(test)]
229mod tests {
230    use super::VtlSet;
231    use hvdef::Vtl;
232
233    #[test]
234    fn test_vtlset() {
235        let mut set = VtlSet::new();
236        assert_eq!(set.highest_set(), None);
237        set.set(Vtl::Vtl0);
238        assert_eq!(set.highest_set(), Some(Vtl::Vtl0));
239        set.set(Vtl::Vtl2);
240        assert_eq!(set.highest_set(), Some(Vtl::Vtl2));
241
242        {
243            let mut iter = set.iter_highest_first();
244            assert_eq!(iter.next(), Some(Vtl::Vtl2));
245            assert_eq!(iter.next(), Some(Vtl::Vtl0));
246            assert_eq!(iter.next(), None);
247        }
248
249        assert!(!set.is_higher_vtl_set_than(Vtl::Vtl2));
250        assert!(set.is_higher_vtl_set_than(Vtl::Vtl1));
251        assert!(set.is_higher_vtl_set_than(Vtl::Vtl0));
252
253        set.clear(Vtl::Vtl2);
254        assert!(!set.is_higher_vtl_set_than(Vtl::Vtl0));
255    }
256}