#[derive(Clone, Debug)]
pub struct LRUList<T> {
values: Vec<ListEntry<T>>,
}
#[derive(Clone, Debug)]
struct ListEntry<T> {
value: Option<T>,
next: usize,
prev: usize,
}
impl<T> LRUList<T> {
const FREE: usize = 0;
const OCCUPIED: usize = 1;
pub(crate) fn with_capacity(capacity: usize) -> LRUList<T> {
let mut values = Vec::with_capacity(capacity + 2);
values.push(ListEntry::<T> {
value: None,
next: 0,
prev: 0,
});
values.push(ListEntry::<T> {
value: None,
next: 1,
prev: 1,
});
LRUList { values }
}
pub(crate) fn unlink(&mut self, index: usize) {
let prev = self.values[index].prev;
let next = self.values[index].next;
self.values[prev].next = next;
self.values[next].prev = prev;
}
pub(crate) fn link_after(&mut self, index: usize, prev: usize) {
let next = self.values[prev].next;
self.values[index].prev = prev;
self.values[index].next = next;
self.values[prev].next = index;
self.values[next].prev = index;
}
pub(crate) fn move_to_front(&mut self, index: usize) {
self.unlink(index);
self.link_after(index, Self::OCCUPIED);
}
pub(crate) fn push_front(&mut self, value: T) -> usize {
if self.values[Self::FREE].next == Self::FREE {
self.values.push(ListEntry::<T> {
value: None,
next: Self::FREE,
prev: Self::FREE,
});
self.values[Self::FREE].next = self.values.len() - 1;
}
let index = self.values[Self::FREE].next;
self.values[index].value = Some(value);
self.unlink(index);
self.link_after(index, Self::OCCUPIED);
index
}
pub(crate) fn remove(&mut self, index: usize) -> T {
self.unlink(index);
self.link_after(index, Self::FREE);
self.values[index].value.take().expect("invalid index")
}
pub(crate) fn back(&self) -> usize {
self.values[Self::OCCUPIED].prev
}
pub(crate) fn get(&self, index: usize) -> &T {
self.values[index].value.as_ref().expect("invalid index")
}
pub(crate) fn get_mut(&mut self, index: usize) -> &mut T {
self.values[index].value.as_mut().expect("invalid index")
}
pub(crate) fn set(&mut self, index: usize, value: T) -> Option<T> {
self.values[index].value.replace(value)
}
pub(crate) fn clear(&mut self) {
self.values.clear();
self.values.push(ListEntry::<T> {
value: None,
next: 0,
prev: 0,
});
self.values.push(ListEntry::<T> {
value: None,
next: 1,
prev: 1,
});
}
pub fn iter(&self) -> LRUListIterator<T> {
LRUListIterator::<T> {
list: self,
index: Self::OCCUPIED,
}
}
}
#[derive(Debug)]
pub struct LRUListIterator<'a, T> {
list: &'a LRUList<T>,
index: usize,
}
impl<'a, T> Iterator for LRUListIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
let next = self.list.values[self.index].next;
if next == LRUList::<T>::OCCUPIED {
None
} else {
let value = self.list.values[next].value.as_ref();
self.index = next;
value
}
}
}