Skip to main content

wowlab_engine_combat/state/
bounded_vec.rs

1//! Finalization-sized runtime vectors whose insertions cannot grow the allocation.
2
3/// Runtime storage with an immutable construction-time element bound.
4#[derive(Debug)]
5pub(crate) struct BoundedVec<T> {
6    values: Vec<T>,
7    limit: usize,
8}
9
10impl<T> BoundedVec<T> {
11    pub(crate) fn new(limit: usize) -> Self {
12        Self {
13            values: Vec::with_capacity(limit),
14            limit,
15        }
16    }
17
18    #[must_use]
19    #[cfg(test)]
20    pub(crate) const fn limit(&self) -> usize {
21        self.limit
22    }
23
24    #[must_use]
25    pub(crate) fn len(&self) -> usize {
26        self.values.len()
27    }
28
29    #[must_use]
30    pub(crate) fn is_empty(&self) -> bool {
31        self.values.is_empty()
32    }
33
34    pub(crate) fn push(&mut self, value: T) {
35        assert!(
36            self.values.len() < self.limit,
37            "bounded runtime vector length {} exhausts finalized limit {}",
38            self.values.len(),
39            self.limit
40        );
41        self.values.push(value);
42    }
43
44    pub(crate) fn clear(&mut self) {
45        self.values.clear();
46    }
47
48    pub(crate) fn retain(&mut self, keep: impl FnMut(&T) -> bool) {
49        self.values.retain(keep);
50    }
51
52    pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut T> {
53        self.values.get_mut(index)
54    }
55
56    pub(crate) fn sort_unstable_by_key<K>(&mut self, key: impl FnMut(&T) -> K)
57    where
58        K: Ord,
59    {
60        self.values.sort_unstable_by_key(key);
61    }
62
63    #[cfg(test)]
64    pub(crate) fn extend(&mut self, values: impl IntoIterator<Item = T>) {
65        for value in values {
66            self.push(value);
67        }
68    }
69}
70
71impl<T> std::ops::Deref for BoundedVec<T> {
72    type Target = [T];
73
74    fn deref(&self) -> &Self::Target {
75        &self.values
76    }
77}
78
79impl<T> std::ops::Index<usize> for BoundedVec<T> {
80    type Output = T;
81
82    fn index(&self, index: usize) -> &Self::Output {
83        // BOUNDS: this type deliberately preserves slice indexing semantics while preventing growth.
84        &self.values[index]
85    }
86}
87
88impl<T> std::ops::IndexMut<usize> for BoundedVec<T> {
89    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
90        // BOUNDS: this type deliberately preserves slice indexing semantics while preventing growth.
91        &mut self.values[index]
92    }
93}
94
95impl<'a, T> IntoIterator for &'a BoundedVec<T> {
96    type Item = &'a T;
97    type IntoIter = std::slice::Iter<'a, T>;
98
99    fn into_iter(self) -> Self::IntoIter {
100        self.values.iter()
101    }
102}
103
104impl<'a, T> IntoIterator for &'a mut BoundedVec<T> {
105    type Item = &'a mut T;
106    type IntoIter = std::slice::IterMut<'a, T>;
107
108    fn into_iter(self) -> Self::IntoIter {
109        self.values.iter_mut()
110    }
111}
112
113impl<T> Default for BoundedVec<T> {
114    fn default() -> Self {
115        Self::new(0)
116    }
117}