use crate::ttl_queue::TtlQueue;
#[derive(Debug, Clone)]
pub struct Inbox<T> {
queue: TtlQueue<T>,
default_ttl_secs: u64,
}
impl<T> Inbox<T> {
pub fn new(capacity: usize, default_ttl_secs: u64) -> Self {
Self {
queue: TtlQueue::new(capacity),
default_ttl_secs,
}
}
pub fn push(&mut self, now: u64, item: T) {
let expires_at = if self.default_ttl_secs == 0 {
0
} else {
now.saturating_add(self.default_ttl_secs)
};
self.queue.push(now, expires_at, item);
}
pub fn push_with_ttl(&mut self, now: u64, ttl_secs: u64, item: T) {
let expires_at = if ttl_secs == 0 {
0
} else {
now.saturating_add(ttl_secs)
};
self.queue.push(now, expires_at, item);
}
pub fn pop(&mut self, now: u64) -> Option<T> {
self.queue.pop(now)
}
pub fn peek(&mut self, now: u64) -> Option<&T> {
self.queue.peek(now)
}
pub fn drain(&mut self, now: u64) -> Vec<T> {
self.queue.drain(now)
}
pub fn len(&self) -> usize {
self.queue.len()
}
pub fn is_empty(&self) -> bool {
self.queue.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_ttl_applied() {
let mut inbox = Inbox::new(8, 60);
inbox.push(100, "msg");
assert_eq!(inbox.peek(100), Some(&"msg"));
assert_eq!(inbox.pop(161), None);
}
#[test]
fn custom_ttl_overrides_default() {
let mut inbox = Inbox::new(8, 60);
inbox.push_with_ttl(100, 10, "short");
inbox.push(100, "default");
assert_eq!(inbox.pop(111), Some("default"));
}
#[test]
fn zero_default_ttl_never_expires() {
let mut inbox = Inbox::new(4, 0);
inbox.push(100, "forever");
assert_eq!(inbox.pop(u64::MAX), Some("forever"));
}
}