#![no_std]
#![cfg_attr(feature = "nightly", feature(alloc, optin_builtin_traits))]
extern crate hashbrown;
#[cfg(test)]
extern crate scoped_threadpool;
#[cfg(not(feature = "nightly"))]
extern crate std as alloc;
use alloc::borrow::Borrow;
use alloc::boxed::Box;
use core::hash::{BuildHasher, Hash, Hasher};
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::mem;
use core::mem::MaybeUninit;
use core::ptr;
use core::usize;
use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::HashMap;
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(feature = "nightly")]
extern crate alloc;
#[doc(hidden)]
pub struct KeyRef<K> {
k: *const K,
}
impl<K: Hash> Hash for KeyRef<K> {
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe { (*self.k).hash(state) }
}
}
impl<K: PartialEq> PartialEq for KeyRef<K> {
fn eq(&self, other: &KeyRef<K>) -> bool {
unsafe { (*self.k).eq(&*other.k) }
}
}
impl<K: Eq> Eq for KeyRef<K> {}
#[cfg(feature = "nightly")]
#[doc(hidden)]
pub auto trait NotKeyRef {}
#[cfg(feature = "nightly")]
impl<K> !NotKeyRef for KeyRef<K> {}
#[cfg(feature = "nightly")]
impl<K, D> Borrow<D> for KeyRef<K>
where
K: Borrow<D>,
D: NotKeyRef + ?Sized,
{
fn borrow(&self) -> &D {
unsafe { (&*self.k) }.borrow()
}
}
#[cfg(not(feature = "nightly"))]
impl<K> Borrow<K> for KeyRef<K> {
fn borrow(&self) -> &K {
unsafe { (&*self.k) }
}
}
struct LruEntry<K, V> {
key: K,
val: V,
prev: *mut LruEntry<K, V>,
next: *mut LruEntry<K, V>,
}
impl<K, V> LruEntry<K, V> {
fn new(key: K, val: V) -> Self {
LruEntry {
key,
val,
prev: ptr::null_mut(),
next: ptr::null_mut(),
}
}
}
pub struct LruCache<K, V, S = DefaultHashBuilder> {
map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>, S>,
cap: usize,
head: *mut LruEntry<K, V>,
tail: *mut LruEntry<K, V>,
}
impl<K: Hash + Eq, V> LruCache<K, V> {
pub fn new(cap: usize) -> LruCache<K, V> {
LruCache::construct(cap, HashMap::with_capacity(cap))
}
pub fn unbounded() -> LruCache<K, V> {
LruCache::construct(usize::MAX, HashMap::default())
}
}
impl<K: Hash + Eq, V, S: BuildHasher> LruCache<K, V, S> {
pub fn with_hasher(cap: usize, hash_builder: S) -> LruCache<K, V, S> {
LruCache::construct(cap, HashMap::with_capacity_and_hasher(cap, hash_builder))
}
fn construct(cap: usize, map: HashMap<KeyRef<K>, Box<LruEntry<K, V>>, S>) -> LruCache<K, V, S> {
let cache = LruCache {
map,
cap,
head: unsafe {
Box::into_raw(Box::new(
MaybeUninit::<LruEntry<K, V>>::uninit().assume_init(),
))
},
tail: unsafe {
Box::into_raw(Box::new(
MaybeUninit::<LruEntry<K, V>>::uninit().assume_init(),
))
},
};
unsafe {
(*cache.head).next = cache.tail;
(*cache.tail).prev = cache.head;
}
cache
}
pub fn put(&mut self, k: K, mut v: V) -> Option<V> {
let node_ptr = self.map.get_mut(&KeyRef { k: &k }).map(|node| {
let node_ptr: *mut LruEntry<K, V> = &mut **node;
node_ptr
});
match node_ptr {
Some(node_ptr) => {
unsafe { mem::swap(&mut v, &mut (*node_ptr).val) }
self.detach(node_ptr);
self.attach(node_ptr);
Some(v)
}
None => {
let mut node = if self.len() == self.cap() {
let old_key = KeyRef {
k: unsafe { &(*(*self.tail).prev).key },
};
let mut old_node = self.map.remove(&old_key).unwrap();
old_node.key = k;
old_node.val = v;
let node_ptr: *mut LruEntry<K, V> = &mut *old_node;
self.detach(node_ptr);
old_node
} else {
Box::new(LruEntry::new(k, v))
};
let node_ptr: *mut LruEntry<K, V> = &mut *node;
self.attach(node_ptr);
let keyref = unsafe { &(*node_ptr).key };
self.map.insert(KeyRef { k: keyref }, node);
None
}
}
}
pub fn get<'a, Q>(&'a mut self, k: &Q) -> Option<&'a V>
where
KeyRef<K>: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
let (node_ptr, value) = match self.map.get_mut(k) {
None => (None, None),
Some(node) => {
let node_ptr: *mut LruEntry<K, V> = &mut **node;
(Some(node_ptr), Some(unsafe { &(*node_ptr).val }))
}
};
match node_ptr {
None => (),
Some(node_ptr) => {
self.detach(node_ptr);
self.attach(node_ptr);
}
}
value
}
pub fn get_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
let key = KeyRef { k };
let (node_ptr, value) = match self.map.get_mut(&key) {
None => (None, None),
Some(node) => {
let node_ptr: *mut LruEntry<K, V> = &mut **node;
(Some(node_ptr), Some(unsafe { &mut (*node_ptr).val }))
}
};
match node_ptr {
None => (),
Some(node_ptr) => {
self.detach(node_ptr);
self.attach(node_ptr);
}
}
value
}
pub fn peek<'a>(&'a self, k: &K) -> Option<&'a V> {
let key = KeyRef { k };
match self.map.get(&key) {
None => None,
Some(node) => Some(&node.val),
}
}
pub fn peek_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
let key = KeyRef { k };
match self.map.get_mut(&key) {
None => None,
Some(node) => Some(&mut node.val),
}
}
pub fn peek_lru<'a>(&'a self) -> Option<(&'a K, &'a V)> {
if self.len() == 0 {
return None;
}
let (key, val);
unsafe {
let node = (*self.tail).prev;
key = &(*node).key;
val = &(*node).val;
}
Some((key, val))
}
pub fn contains(&self, k: &K) -> bool {
let key = KeyRef { k };
self.map.contains_key(&key)
}
pub fn pop(&mut self, k: &K) -> Option<V> {
let key = KeyRef { k };
match self.map.remove(&key) {
None => None,
Some(mut old_node) => {
let node_ptr: *mut LruEntry<K, V> = &mut *old_node;
self.detach(node_ptr);
Some(old_node.val)
}
}
}
pub fn pop_lru(&mut self) -> Option<(K, V)> {
let node = self.remove_last()?;
let node = *node;
let LruEntry { key, val, .. } = node;
Some((key, val))
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.len() == 0
}
pub fn cap(&self) -> usize {
self.cap
}
pub fn resize(&mut self, cap: usize) {
if cap == self.cap {
return;
}
while self.map.len() > cap {
self.remove_last();
}
self.map.shrink_to_fit();
self.cap = cap;
}
pub fn clear(&mut self) {
loop {
match self.remove_last() {
Some(_) => (),
None => break,
}
}
}
pub fn iter<'a>(&'a self) -> Iter<'a, K, V> {
Iter {
len: self.len(),
ptr: unsafe { (*self.head).next },
end: unsafe { (*self.tail).prev },
phantom: PhantomData,
}
}
pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, K, V> {
IterMut {
len: self.len(),
ptr: unsafe { (*self.head).next },
end: unsafe { (*self.tail).prev },
phantom: PhantomData,
}
}
fn remove_last(&mut self) -> Option<Box<LruEntry<K, V>>> {
let prev;
unsafe { prev = (*self.tail).prev }
if prev != self.head {
let old_key = KeyRef {
k: unsafe { &(*(*self.tail).prev).key },
};
let mut old_node = self.map.remove(&old_key).unwrap();
let node_ptr: *mut LruEntry<K, V> = &mut *old_node;
self.detach(node_ptr);
Some(old_node)
} else {
None
}
}
fn detach(&mut self, node: *mut LruEntry<K, V>) {
unsafe {
(*(*node).prev).next = (*node).next;
(*(*node).next).prev = (*node).prev;
}
}
fn attach(&mut self, node: *mut LruEntry<K, V>) {
unsafe {
(*node).next = (*self.head).next;
(*node).prev = self.head;
(*self.head).next = node;
(*(*node).next).prev = node;
}
}
}
impl<K, V, S> Drop for LruCache<K, V, S> {
fn drop(&mut self) {
unsafe {
let head = *Box::from_raw(self.head);
let tail = *Box::from_raw(self.tail);
let LruEntry {
key: head_key,
val: head_val,
..
} = head;
let LruEntry {
key: tail_key,
val: tail_val,
..
} = tail;
mem::forget(head_key);
mem::forget(head_val);
mem::forget(tail_key);
mem::forget(tail_val);
}
}
}
impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a LruCache<K, V, S> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
fn into_iter(self) -> Iter<'a, K, V> {
self.iter()
}
}
impl<'a, K: Hash + Eq, V, S: BuildHasher> IntoIterator for &'a mut LruCache<K, V, S> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
fn into_iter(self) -> IterMut<'a, K, V> {
self.iter_mut()
}
}
unsafe impl<K: Send, V: Send> Send for LruCache<K, V> {}
unsafe impl<K: Sync, V: Sync> Sync for LruCache<K, V> {}
pub struct Iter<'a, K: 'a, V: 'a> {
len: usize,
ptr: *const LruEntry<K, V>,
end: *const LruEntry<K, V>,
phantom: PhantomData<&'a K>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
if self.len == 0 {
return None;
}
let key = unsafe { &(*self.ptr).key };
let val = unsafe { &(*self.ptr).val };
self.len -= 1;
self.ptr = unsafe { (*self.ptr).next };
Some((key, val))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
fn count(self) -> usize {
self.len
}
}
impl<'a, K, V> DoubleEndedIterator for Iter<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
if self.len == 0 {
return None;
}
let key = unsafe { &(*self.end).key };
let val = unsafe { &(*self.end).val };
self.len -= 1;
self.end = unsafe { (*self.end).prev };
Some((key, val))
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
impl<'a, K, V> Clone for Iter<'a, K, V> {
fn clone(&self) -> Iter<'a, K, V> {
Iter {
len: self.len,
ptr: self.ptr,
end: self.end,
phantom: PhantomData,
}
}
}
unsafe impl<'a, K: Send, V: Send> Send for Iter<'a, K, V> {}
unsafe impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V> {}
pub struct IterMut<'a, K: 'a, V: 'a> {
len: usize,
ptr: *mut LruEntry<K, V>,
end: *mut LruEntry<K, V>,
phantom: PhantomData<&'a K>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
if self.len == 0 {
return None;
}
let key = unsafe { &(*self.ptr).key };
let val = unsafe { &mut (*self.ptr).val };
self.len -= 1;
self.ptr = unsafe { (*self.ptr).next };
Some((key, val))
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
fn count(self) -> usize {
self.len
}
}
impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
if self.len == 0 {
return None;
}
let key = unsafe { &(*self.end).key };
let val = unsafe { &mut (*self.end).val };
self.len -= 1;
self.end = unsafe { (*self.end).prev };
Some((key, val))
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {}
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {}
unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {}