#[cfg(feature = "fake_clock")]
use fake_clock::FakeClock as Instant;
use std::collections::{BTreeMap, VecDeque};
use std::time::Duration;
#[cfg(not(feature = "fake_clock"))]
use std::time::Instant;
pub struct Iter<'a, Key, Value> {
map: &'a mut BTreeMap<Key, (Value, Instant)>,
list: &'a mut VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
item_index: usize,
}
impl<'a, Key, Value> Iter<'a, Key, Value>
where
Key: Ord,
{
#[doc(hidden)]
pub fn new(
map: &'a mut BTreeMap<Key, (Value, Instant)>,
list: &'a mut VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
) -> Self {
let item_index = list.len();
Self {
map,
list,
lru_cache_ttl,
item_index,
}
}
fn next_unexpired(&mut self, now: Instant) -> Option<Key> {
loop {
self.item_index = self.item_index.checked_sub(1)?;
let key = self.list.remove(self.item_index)?;
let value = self.map.get(&key)?;
if let Some(ttl) = self.lru_cache_ttl {
if value.1 + ttl > now {
return Some(key);
} else {
let _ = self.map.remove(&key);
}
} else {
return Some(key);
}
}
}
}
impl<'a, Key, Value> Iterator for Iter<'a, Key, Value>
where
Key: Ord + Clone,
{
type Item = (&'a Key, &'a Value);
#[allow(unsafe_code)]
fn next(&mut self) -> Option<(&'a Key, &'a Value)> {
let now = Instant::now();
let key = self.next_unexpired(now)?;
self.list.push_back(key);
let key = self.list.back()?;
let mut value = self.map.get_mut(&key)?;
value.1 = now;
unsafe {
let key = std::mem::transmute::<&Key, &'a Key>(key);
let value = std::mem::transmute::<&Value, &'a Value>(&value.0);
Some((key, value))
}
}
}
pub enum TimedEntry<'a, Key: 'a, Value: 'a> {
Valid(&'a Key, &'a Value),
Expired(Key, Value),
}
pub struct NotifyIter<'a, Key, Value> {
map: &'a mut BTreeMap<Key, (Value, Instant)>,
list: &'a mut VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
item_index: usize,
}
impl<'a, Key, Value> NotifyIter<'a, Key, Value>
where
Key: Ord + Clone,
{
#[doc(hidden)]
pub fn new(
map: &'a mut BTreeMap<Key, (Value, Instant)>,
list: &'a mut VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
) -> Self {
let item_index = list.len();
Self {
map,
list,
lru_cache_ttl,
item_index,
}
}
}
impl<'a, Key, Value> Iterator for NotifyIter<'a, Key, Value>
where
Key: Ord + Clone,
{
type Item = TimedEntry<'a, Key, Value>;
#[allow(unsafe_code)]
fn next(&mut self) -> Option<Self::Item> {
self.item_index = self.item_index.checked_sub(1)?;
let key = self.list.remove(self.item_index)?;
let mut value = self.map.get_mut(&key)?;
let now = Instant::now();
if let Some(ttl) = self.lru_cache_ttl {
if value.1 + ttl <= now {
let value = self.map.remove(&key)?;
return Some(TimedEntry::Expired(key, value.0));
}
}
self.list.push_back(key);
let key = self.list.back()?;
value.1 = now;
unsafe {
let key = std::mem::transmute::<&Key, &'a Key>(key);
let value = std::mem::transmute::<&Value, &'a Value>(&value.0);
Some(TimedEntry::Valid(key, value))
}
}
}
pub struct PeekIter<'a, Key, Value> {
map: &'a BTreeMap<Key, (Value, Instant)>,
list: &'a VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
item_index: usize,
}
impl<'a, Key, Value> PeekIter<'a, Key, Value>
where
Key: Ord,
{
#[doc(hidden)]
pub fn new(
map: &'a BTreeMap<Key, (Value, Instant)>,
list: &'a VecDeque<Key>,
lru_cache_ttl: Option<Duration>,
) -> Self {
let item_index = list.len();
Self {
map,
list,
lru_cache_ttl,
item_index,
}
}
fn next_unexpired(&mut self, now: Instant) -> Option<()> {
loop {
self.item_index = self.item_index.checked_sub(1)?;
let value = self.map.get(&self.list[self.item_index])?;
if let Some(ttl) = self.lru_cache_ttl {
if value.1 + ttl > now {
return Some(());
}
} else {
return Some(());
}
}
}
}
impl<'a, Key, Value> Iterator for PeekIter<'a, Key, Value>
where
Key: Ord + Clone,
{
type Item = (&'a Key, &'a Value);
#[allow(unsafe_code)]
fn next(&mut self) -> Option<(&'a Key, &'a Value)> {
let now = Instant::now();
self.next_unexpired(now)?;
let key = &self.list[self.item_index];
let value = self.map.get(&key)?;
unsafe {
let key = std::mem::transmute::<&Key, &'a Key>(key);
let value = std::mem::transmute::<&Value, &'a Value>(&value.0);
Some((key, value))
}
}
}