use hashbrown::HashMap;
use std::collections::VecDeque;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::h2) struct ClosedStream {
pub(in crate::h2) reason: ClosedReason,
pub(in crate::h2) ignore_late_frames: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::h2) enum ClosedReason {
Reset,
EndStream,
}
#[derive(Debug, Default)]
pub(super) struct ClosedStreams {
map: HashMap<u32, ClosedStream>,
fifo: VecDeque<u32>,
}
impl ClosedStreams {
pub(super) const CAP: usize = 128;
pub(super) fn record_close(&mut self, stream_id: u32, reason: ClosedReason) {
self.entry(stream_id, reason);
}
pub(super) fn record_local_reset(&mut self, stream_id: u32) {
self.entry(stream_id, ClosedReason::Reset)
.ignore_late_frames = true;
}
pub(super) fn record_peer_reset(&mut self, stream_id: u32) {
self.entry(stream_id, ClosedReason::Reset)
.ignore_late_frames = false;
}
pub(super) fn get(&self, stream_id: u32) -> Option<ClosedStream> {
self.map.get(&stream_id).copied()
}
fn entry(&mut self, stream_id: u32, reason: ClosedReason) -> &mut ClosedStream {
if !self.map.contains_key(&stream_id) {
self.fifo.push_back(stream_id);
while self.fifo.len() > Self::CAP {
if let Some(old) = self.fifo.pop_front() {
self.map.remove(&old);
}
}
}
let closed = self.map.entry(stream_id).or_insert(ClosedStream {
reason,
ignore_late_frames: false,
});
if reason == ClosedReason::Reset {
closed.reason = ClosedReason::Reset;
}
closed
}
}