1#![warn(missing_docs)]
4#![no_std]
5
6extern crate alloc;
7
8use alloc::boxed::Box;
9use core::{fmt, iter::FusedIterator, marker::PhantomData, ptr::addr_of_mut};
10
11#[derive(Clone)]
13pub struct LruSlab<T> {
14 slots: Box<[Slot<T>]>,
15 head: u32,
17 tail: u32,
19 free: u32,
21 len: u32,
23}
24
25impl<T> LruSlab<T> {
26 pub fn new() -> Self {
28 Self::with_capacity(0)
29 }
30
31 pub fn with_capacity(capacity: u32) -> Self {
33 assert!(capacity != u32::MAX, "capacity too large");
34 Self {
35 slots: (0..capacity)
36 .map(|n| Slot {
37 value: None,
38 prev: NONE,
39 next: if n + 1 == capacity { NONE } else { n + 1 },
40 })
41 .collect(),
42 head: NONE,
43 tail: NONE,
44 free: if capacity == 0 { NONE } else { 0 },
45 len: 0,
46 }
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.len == 0
52 }
53
54 pub fn len(&self) -> u32 {
56 self.len
57 }
58
59 pub fn capacity(&self) -> u32 {
61 self.slots.len() as u32
62 }
63
64 pub fn vacant_key(&self) -> u32 {
66 match self.free {
67 NONE => self.capacity(),
68 _ => self.free,
69 }
70 }
71
72 pub fn insert(&mut self, value: T) -> u32 {
76 let id = match self.alloc() {
77 Some(id) => id,
78 None => {
79 let len = self.capacity();
80 let cap = 2u32.saturating_mul(len.max(2)).min(u32::MAX - 1);
82 if cap == len {
83 panic!("cannot store more than 2^32-2 elements");
84 }
85 self.slots = self
86 .slots
87 .iter_mut()
88 .map(|x| Slot {
89 value: x.value.take(),
90 next: x.next,
91 prev: x.prev,
92 })
93 .chain((len..cap).map(|n| Slot {
94 value: None,
95 prev: NONE,
96 next: if n + 1 == cap { NONE } else { n + 1 },
97 }))
98 .collect();
99 self.free = len + 1;
100 len
101 }
102 };
103 let idx = id as usize;
104
105 debug_assert!(self.slots[idx].value.is_none(), "corrupt free list");
106 self.slots[idx].value = Some(value);
107 self.link_at_head(id);
108 self.len += 1;
109
110 id
111 }
112
113 pub fn lru(&self) -> Option<u32> {
115 if self.tail == NONE {
116 debug_assert_eq!(self.head, NONE);
117 None
118 } else {
119 Some(self.tail)
120 }
121 }
122
123 pub fn remove(&mut self, slot: u32) -> T {
125 self.unlink(slot);
126 self.slots[slot as usize].next = self.free;
127 self.slots[slot as usize].prev = NONE;
128 self.free = slot;
129 self.len -= 1;
130 self.slots[slot as usize]
131 .value
132 .take()
133 .expect("removing empty slot")
134 }
135
136 pub fn get_mut(&mut self, slot: u32) -> &mut T {
138 self.freshen(slot);
139 self.peek_mut(slot)
140 }
141
142 pub fn peek(&self, slot: u32) -> &T {
144 self.slots[slot as usize].value.as_ref().unwrap()
145 }
146
147 pub fn peek_mut(&mut self, slot: u32) -> &mut T {
149 self.slots[slot as usize].value.as_mut().unwrap()
150 }
151
152 pub fn iter(&self) -> Iter<'_, T> {
154 let state = IterState::new(self);
155 Iter {
156 slots: &self.slots[..],
157 state,
158 }
159 }
160
161 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
163 let state = IterState::new(self);
164 IterMut {
165 slots: self.slots[..].as_mut_ptr().cast(),
166 state,
167 _marker: PhantomData,
168 }
169 }
170
171 fn alloc(&mut self) -> Option<u32> {
173 if self.free == NONE {
174 return None;
175 }
176 let slot = self.free;
177 self.free = self.slots[slot as usize].next;
178 Some(slot)
179 }
180
181 fn freshen(&mut self, slot: u32) {
183 if self.slots[slot as usize].prev == NONE {
184 debug_assert_eq!(self.head, slot, "corrupt LRU list");
186 return;
187 }
188
189 self.unlink(slot);
190 self.link_at_head(slot);
191 }
192
193 fn link_at_head(&mut self, slot: u32) {
195 let idx = slot as usize;
196 if self.head == NONE {
197 self.slots[idx].next = NONE;
199 self.tail = slot;
200 } else {
201 self.slots[idx].next = self.head;
202 self.slots[self.head as usize].prev = slot;
203 }
204 self.slots[idx].prev = NONE;
205 self.head = slot;
206 }
207
208 fn unlink(&mut self, slot: u32) {
210 let idx = slot as usize;
211 if self.slots[idx].prev != NONE {
212 self.slots[self.slots[idx].prev as usize].next = self.slots[idx].next;
213 } else {
214 self.head = self.slots[idx].next;
215 }
216 if self.slots[idx].next != NONE {
217 self.slots[self.slots[idx].next as usize].prev = self.slots[idx].prev;
218 } else {
219 self.tail = self.slots[idx].prev;
221 }
222 }
223}
224
225impl<T> Default for LruSlab<T> {
226 fn default() -> Self {
227 Self::new()
228 }
229}
230
231impl<T> FromIterator<T> for LruSlab<T> {
232 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
233 let iter = iter.into_iter();
234 let mut slab = LruSlab::with_capacity(u32::try_from(iter.size_hint().0).unwrap());
235 for x in iter {
236 slab.insert(x);
237 }
238 slab
239 }
240}
241
242impl<'a, T> IntoIterator for &'a LruSlab<T> {
243 type Item = (u32, &'a T);
244
245 type IntoIter = Iter<'a, T>;
246
247 fn into_iter(self) -> Self::IntoIter {
248 self.iter()
249 }
250}
251
252impl<'a, T> IntoIterator for &'a mut LruSlab<T> {
253 type Item = (u32, &'a mut T);
254
255 type IntoIter = IterMut<'a, T>;
256
257 fn into_iter(self) -> Self::IntoIter {
258 self.iter_mut()
259 }
260}
261
262impl<T: fmt::Debug> fmt::Debug for LruSlab<T> {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 f.debug_map().entries(self).finish()
265 }
266}
267
268#[derive(Clone)]
269struct Slot<T> {
270 value: Option<T>,
271 next: u32,
273 prev: u32,
275}
276
277const NONE: u32 = u32::MAX;
278
279pub struct Iter<'a, T> {
281 slots: &'a [Slot<T>],
282 state: IterState,
283}
284
285impl<'a, T> Iterator for Iter<'a, T> {
286 type Item = (u32, &'a T);
287 fn next(&mut self) -> Option<(u32, &'a T)> {
288 let idx = self.state.next(|i| self.slots[i as usize].next)?;
289 let result = self.slots[idx as usize]
290 .value
291 .as_ref()
292 .expect("corrupt LRU list");
293 Some((idx, result))
294 }
295
296 fn size_hint(&self) -> (usize, Option<usize>) {
297 (self.state.len as usize, Some(self.state.len as usize))
298 }
299}
300
301impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
302 fn next_back(&mut self) -> Option<(u32, &'a T)> {
303 let idx = self.state.next_back(|i| self.slots[i as usize].prev)?;
304 let result = self.slots[idx as usize]
305 .value
306 .as_ref()
307 .expect("corrupt LRU list");
308 Some((idx, result))
309 }
310}
311
312impl<T> ExactSizeIterator for Iter<'_, T> {
313 fn len(&self) -> usize {
314 self.state.len as usize
315 }
316}
317
318impl<T> FusedIterator for Iter<'_, T> {}
319
320pub struct IterMut<'a, T> {
322 slots: *mut Slot<T>,
323 state: IterState,
324 _marker: PhantomData<&'a mut [Slot<T>]>,
325}
326
327impl<'a, T> Iterator for IterMut<'a, T> {
328 type Item = (u32, &'a mut T);
329 fn next(&mut self) -> Option<(u32, &'a mut T)> {
330 unsafe {
333 let idx = self
334 .state
335 .next(|i| *addr_of_mut!((*self.slots.add(i as usize)).next))?;
336 let result = (*addr_of_mut!((*self.slots.add(idx as usize)).value))
337 .as_mut()
338 .expect("corrupt LRU list");
339 Some((idx, result))
340 }
341 }
342
343 fn size_hint(&self) -> (usize, Option<usize>) {
344 (self.state.len as usize, Some(self.state.len as usize))
345 }
346}
347
348impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
349 fn next_back(&mut self) -> Option<(u32, &'a mut T)> {
350 unsafe {
353 let idx = self
354 .state
355 .next_back(|i| *addr_of_mut!((*self.slots.add(i as usize)).prev))?;
356 let result = (*addr_of_mut!((*self.slots.add(idx as usize)).value))
357 .as_mut()
358 .expect("corrupt LRU list");
359 Some((idx, result))
360 }
361 }
362}
363
364impl<T> ExactSizeIterator for IterMut<'_, T> {
365 fn len(&self) -> usize {
366 self.state.len as usize
367 }
368}
369
370impl<T> FusedIterator for IterMut<'_, T> {}
371
372struct IterState {
373 head: u32,
374 tail: u32,
375 len: u32,
376}
377
378impl IterState {
379 fn new<T>(slab: &LruSlab<T>) -> Self {
380 Self {
381 head: slab.head,
382 tail: slab.tail,
383 len: slab.len,
384 }
385 }
386
387 fn next(&mut self, get_next: impl Fn(u32) -> u32) -> Option<u32> {
388 if self.len == 0 {
389 return None;
390 }
391 let idx = self.head;
392 self.head = get_next(idx);
393 self.len -= 1;
394 Some(idx)
395 }
396
397 fn next_back(&mut self, get_prev: impl Fn(u32) -> u32) -> Option<u32> {
398 if self.len == 0 {
399 return None;
400 }
401 let idx = self.tail;
402 self.tail = get_prev(idx);
403 self.len -= 1;
404 Some(idx)
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use alloc::{format, string::String, vec::Vec};
411
412 use super::*;
413
414 #[test]
415 fn lru_order() {
416 let mut cache = LruSlab::new();
417 let b = cache.insert('b');
418 assert_eq!(cache.iter().map(|(_, x)| x).collect::<String>(), "b");
419 let _a = cache.insert('a');
420 assert_eq!(cache.iter().map(|(_, x)| x).collect::<String>(), "ab");
421 let d = cache.insert('d');
422 assert_eq!(cache.iter().map(|(_, x)| x).collect::<String>(), "dab");
423 let c = cache.insert('c');
424 assert_eq!(cache.iter().map(|(_, x)| x).collect::<String>(), "cdab");
425 let e = cache.insert('e');
426 assert_eq!(cache.iter().map(|(_, x)| x).collect::<String>(), "ecdab");
427
428 cache.get_mut(b);
429 cache.get_mut(c);
430 cache.get_mut(d);
431 cache.get_mut(e);
432
433 assert_eq!(cache.remove(cache.lru().unwrap()), 'a');
434 assert_eq!(cache.remove(cache.lru().unwrap()), 'b');
435 assert_eq!(cache.remove(cache.lru().unwrap()), 'c');
436 assert_eq!(cache.remove(cache.lru().unwrap()), 'd');
437 assert_eq!(cache.remove(cache.lru().unwrap()), 'e');
438 assert!(cache.lru().is_none());
439 }
440
441 #[test]
442 fn slot_reuse() {
443 let mut cache = LruSlab::new();
444 let a = cache.insert('a');
445 cache.remove(a);
446 let a_prime = cache.insert('a');
447 assert_eq!(a, a_prime);
448 assert_eq!(cache.len(), 1);
449 }
450
451 #[test]
452 fn debug() {
453 let slab = ['a', 'b'].into_iter().collect::<LruSlab<_>>();
454 assert_eq!(format!("{:?}", slab), "{1: 'b', 0: 'a'}");
455 }
456
457 #[test]
458 fn iter_reverse() {
459 let slab = ['a', 'b'].into_iter().collect::<LruSlab<_>>();
460 let mut double_reversed = slab.iter().rev().collect::<Vec<_>>();
461 double_reversed.reverse();
462 assert_eq!(slab.iter().collect::<Vec<_>>(), double_reversed);
463 }
464
465 #[test]
466 fn vacant_key() {
467 let mut slab = LruSlab::new();
468 assert_eq!(slab.vacant_key(), 0);
469 slab.insert(());
470 assert_eq!(slab.vacant_key(), 1);
471 slab.remove(0);
472 assert_eq!(slab.vacant_key(), 0);
473 }
474}