use std::collections::VecDeque;
use std::sync::Mutex;
pub const SIG_GOODBYE: u8 = 0x02;
pub const SIG_DISCARD: u8 = 0x2F;
pub const SIG_PULL: u8 = 0x3F;
#[derive(Default)]
pub struct DiscardTracker {
pending: Mutex<VecDeque<bool>>,
}
impl DiscardTracker {
pub fn new() -> std::sync::Arc<Self> {
std::sync::Arc::new(Self::default())
}
fn lock(&self) -> std::sync::MutexGuard<'_, VecDeque<bool>> {
self.pending.lock().unwrap_or_else(|p| p.into_inner())
}
pub fn request_arrived(&self, signature: u8, was_discard: bool) {
if signature != SIG_GOODBYE {
self.lock().push_back(was_discard);
}
}
pub fn answering_discard(&self) -> bool {
self.lock().front().copied().unwrap_or(false)
}
pub fn response_closed(&self) {
self.lock().pop_front();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn entries_are_consumed_in_arrival_order() {
let t = DiscardTracker::new();
t.request_arrived(0x10, false);
t.request_arrived(SIG_PULL, true);
t.request_arrived(SIG_GOODBYE, false);
assert!(!t.answering_discard());
t.response_closed();
assert!(t.answering_discard());
t.response_closed();
assert!(!t.answering_discard(), "GOODBYE queued nothing");
}
}