1#[cfg(test)]
3mod tests;
4use core::ops::Index;
5#[derive(Debug)]
9pub struct Cache<T, const N: usize> {
10 vals: [T; N],
12 len: usize,
16 next_head: usize,
18}
19impl<T, const N: usize> Cache<T, N> {
20 #[inline]
24 pub const fn len(&self) -> usize {
25 self.len
26 }
27 #[inline]
29 pub const fn is_empty(&self) -> bool {
30 self.len == 0
31 }
32}
33macro_rules! cache {
38 ( $( $x:literal),* ) => {
39 $(
40impl<T> Cache<T, $x> {
41 #[inline]
46 pub fn get(&self, idx: usize) -> Option<&T> {
47 (idx < self.len).then(|| self.vals.index(self.next_head.wrapping_sub(1).wrapping_sub(idx) & ($x - 1)))
48 }
49 #[inline]
58 pub fn get_unchecked(&self, idx: usize) -> &T {
59 self.vals.index(self.next_head.wrapping_sub(1).wrapping_sub(idx) & ($x - 1))
60 }
61 #[expect(clippy::arithmetic_side_effects, reason = "must, and overflow is not possible")]
64 #[expect(clippy::indexing_slicing, reason = "wont panic since next_head is always correct")]
65 #[inline]
66 pub fn push(&mut self, val: T) {
67 if self.len < $x {
68 self.len += 1;
69 }
70 self.vals[self.next_head] = val;
73 self.next_head = (self.next_head + 1) & ($x - 1);
74 }
75}
76impl<T> Index<usize> for Cache<T, $x> {
77 type Output = T;
78 #[inline]
79 fn index(&self, index: usize) -> &Self::Output {
80 self.get(index).unwrap()
81 }
82}
83 )*
84 };
85}
86cache!(
88 0x1,
89 0x2,
90 0x4,
91 0x8,
92 0x10,
93 0x20,
94 0x40,
95 0x80,
96 0x100,
97 0x200,
98 0x400,
99 0x800,
100 0x1000,
101 0x2000,
102 0x4000,
103 0x8000,
104 0x0001_0000,
105 0x0002_0000,
106 0x0004_0000,
107 0x0008_0000,
108 0x0010_0000,
109 0x0020_0000,
110 0x0040_0000,
111 0x0080_0000,
112 0x0100_0000,
113 0x0200_0000,
114 0x0400_0000,
115 0x0800_0000,
116 0x1000_0000,
117 0x2000_0000,
118 0x4000_0000,
119 0x8000_0000,
120 0x0001_0000_0000,
121 0x0002_0000_0000,
122 0x0004_0000_0000,
123 0x0008_0000_0000,
124 0x0010_0000_0000,
125 0x0020_0000_0000,
126 0x0040_0000_0000,
127 0x0080_0000_0000,
128 0x0100_0000_0000,
129 0x0200_0000_0000,
130 0x0400_0000_0000,
131 0x0800_0000_0000,
132 0x1000_0000_0000,
133 0x2000_0000_0000,
134 0x4000_0000_0000,
135 0x8000_0000_0000,
136 0x0001_0000_0000_0000,
137 0x0002_0000_0000_0000,
138 0x0004_0000_0000_0000,
139 0x0008_0000_0000_0000,
140 0x0010_0000_0000_0000,
141 0x0020_0000_0000_0000,
142 0x0040_0000_0000_0000,
143 0x0080_0000_0000_0000,
144 0x0100_0000_0000_0000,
145 0x0200_0000_0000_0000,
146 0x0400_0000_0000_0000,
147 0x0800_0000_0000_0000,
148 0x1000_0000_0000_0000,
149 0x2000_0000_0000_0000,
150 0x4000_0000_0000_0000,
151 0x8000_0000_0000_0000
152);
153impl<T, const N: usize> Cache<T, N>
154where
155 [T; N]: Default,
156{
157 #[inline]
162 #[must_use]
163 pub fn new() -> Self {
164 Self::default()
165 }
166}
167impl<T, const N: usize> Default for Cache<T, N>
168where
169 [T; N]: Default,
170{
171 #[inline]
172 fn default() -> Self {
173 Self {
174 vals: Default::default(),
175 len: 0,
176 next_head: 0,
177 }
178 }
179}