use std::collections::HashMap;
pub struct HoldTable {
slots: HashMap<String, Vec<u8>>,
max_slots: usize,
drops: u64,
}
impl Default for HoldTable {
fn default() -> Self {
Self {
slots: HashMap::new(),
max_slots: Self::DEFAULT_MAX_SLOTS,
drops: 0,
}
}
}
impl HoldTable {
pub const DEFAULT_MAX_SLOTS: usize = 1024;
pub fn new() -> Self {
Self::default()
}
pub fn with_max_slots(max_slots: usize) -> Self {
Self {
slots: HashMap::new(),
max_slots,
drops: 0,
}
}
pub fn stash(&mut self, slot: &str, bytes: Vec<u8>) {
if self.slots.contains_key(slot) || self.slots.len() < self.max_slots {
self.slots.insert(slot.to_string(), bytes);
} else {
self.drops += 1;
}
}
pub fn flush(&mut self, slot: &str) -> Option<Vec<u8>> {
self.slots.remove(slot)
}
pub fn drops(&self) -> u64 {
self.drops
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stash_flush_roundtrip() {
let mut t = HoldTable::new();
t.stash("a", vec![1, 2, 3]);
assert_eq!(t.flush("a"), Some(vec![1, 2, 3]));
assert_eq!(t.flush("a"), None);
}
#[test]
fn stash_overflow_drops_new_slot_and_ticks_counter() {
let mut t = HoldTable::with_max_slots(2);
t.stash("a", vec![1]);
t.stash("b", vec![2]);
assert_eq!(t.drops(), 0);
t.stash("c", vec![3]);
assert_eq!(t.drops(), 1);
assert_eq!(t.flush("c"), None);
t.stash("a", vec![9]);
assert_eq!(t.flush("a"), Some(vec![9]));
}
}