use ahash::HashMap;
use slab::Slab;
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::mem;
use std::time::Instant;
use crate::store::decorator::Ordered;
use crate::store::item::{Key, Value};
use crate::store::{
Store, StoreIterable, StoreIterableMut, StoreMut, StoreMutRef,
};
mod item;
mod iter;
pub use item::Item;
pub use iter::{Iter, IterMut, Keys, Values};
#[derive(Clone)]
pub struct Queue<K, V, S = HashMap<K, Item>> {
store: Ordered<K, Item, S>,
items: Slab<V>,
}
impl<K, V, S> Queue<K, V, S>
where
K: Key,
S: Store<K, Item>,
{
#[must_use]
pub fn new() -> Self
where
S: Default,
{
Self {
store: Ordered::new(),
items: Slab::new(),
}
}
#[inline]
pub fn get_deadline(&self, key: &K) -> Option<Instant> {
self.store.get(key).map(Item::deadline)
}
}
impl<K, V, S> Queue<K, V, S>
where
K: Key,
S: StoreMut<K, Item>,
{
#[inline]
pub fn set_deadline(
&mut self, key: &K, deadline: Instant,
) -> Option<Instant> {
self.store.remove(key).and_then(|mut item| {
item.set_deadline(deadline);
self.store
.insert(key.clone(), item)
.map(|prior| prior.deadline())
})
}
}
impl<K, V, S> Queue<K, V, S>
where
K: Key,
V: Value,
S: StoreMut<K, Item> + StoreIterable<K, Item>,
{
#[inline]
pub fn deadline(&self) -> Option<Instant> {
self.store.iter().next().map(|(_, item)| item.deadline())
}
#[allow(clippy::missing_panics_doc)]
#[inline]
pub fn take(&mut self) -> Option<(K, V)> {
let deadline = Instant::now();
let opt = self.store.iter().next().and_then(|(key, item)| {
(item.deadline() <= deadline).then(|| key.clone())
});
opt.map(|key| {
self.remove(&key)
.map(|value| (key, value))
.expect("invariant")
})
}
}
impl<K, V, S> Store<K, V> for Queue<K, V, S>
where
K: Key,
S: Store<K, Item>,
{
#[inline]
fn get<Q>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Key,
{
match self.store.get(key) {
Some(item) => self.items.get(*item.data()),
None => None,
}
}
#[inline]
fn contains_key<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Key,
{
self.store.contains_key(key)
}
#[inline]
fn len(&self) -> usize {
self.store.len()
}
}
impl<K, V, S> StoreMut<K, V> for Queue<K, V, S>
where
K: Key,
V: Value,
S: StoreMut<K, Item>,
{
#[inline]
fn insert(&mut self, key: K, value: V) -> Option<V> {
if let Some(item) = self.store.get(&key) {
let prior = &mut self.items[*item.data()];
(prior != &value).then(|| mem::replace(prior, value))
} else {
let index = self.items.insert(value);
self.store.insert(key, Item::new(index));
None
}
}
#[inline]
fn remove<Q>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Key,
{
self.store
.remove(key)
.map(|item| self.items.remove(*item.data()))
}
#[inline]
fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
where
K: Borrow<Q>,
Q: Key,
{
self.store
.remove_entry(key)
.map(|(key, item)| (key, self.items.remove(*item.data())))
}
#[inline]
fn clear(&mut self) {
self.store.clear();
self.items.clear();
}
}
impl<K, V, S> StoreMutRef<K, V> for Queue<K, V, S>
where
K: Key,
S: StoreMut<K, Item>,
{
#[inline]
fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
where
K: Borrow<Q>,
Q: Key,
{
match self.store.get(key) {
Some(item) => self.items.get_mut(*item.data()),
None => None,
}
}
#[inline]
fn get_or_insert_default(&mut self, key: &K) -> &mut V
where
V: Default,
{
if !self.store.contains_key(key) {
let index = self.items.insert(V::default());
self.store.insert(key.clone(), Item::new(index));
}
self.get_mut(key).expect("invariant")
}
}
#[allow(clippy::into_iter_without_iter)]
impl<'a, K, V, S> IntoIterator for &'a Queue<K, V, S>
where
K: Key,
V: Value,
S: StoreIterable<K, Item>,
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[allow(clippy::into_iter_without_iter)]
impl<'a, K, V, S> IntoIterator for &'a mut Queue<K, V, S>
where
K: Key,
V: Value,
S: StoreMut<K, Item> + StoreIterable<K, Item>,
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K, V> Default for Queue<K, V>
where
K: Key,
{
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<K, V, S> Debug for Queue<K, V, S>
where
K: Debug,
V: Debug,
S: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Queue")
.field("store", &self.store)
.field("items", &self.items)
.finish()
}
}