use std::collections::VecDeque;
use std::sync::Arc;
use super::filter::Filter;
use super::CaptureFrame;
#[derive(Debug)]
pub(crate) struct Ring {
frames: VecDeque<Arc<CaptureFrame>>,
first: u64,
capacity: usize,
kept: VecDeque<u64>,
filter: Filter,
}
impl Ring {
pub(crate) fn new(capacity: usize) -> Self {
Self {
frames: VecDeque::new(),
first: 1,
capacity: capacity.max(1),
kept: VecDeque::new(),
filter: Filter::default(),
}
}
pub(crate) fn push(&mut self, frame: CaptureFrame) -> u64 {
if self.frames.len() == self.capacity {
self.frames.pop_front();
if self.kept.front() == Some(&self.first) {
self.kept.pop_front();
}
self.first += 1;
}
let number = self.next();
if self.filter.matches(&frame) {
self.kept.push_back(number);
}
self.frames.push_back(Arc::new(frame));
number
}
pub(crate) fn next(&self) -> u64 {
self.first + self.frames.len() as u64
}
pub(crate) fn len(&self) -> usize {
self.frames.len()
}
pub(crate) fn capacity(&self) -> usize {
self.capacity
}
pub(crate) fn get(&self, number: u64) -> Option<&CaptureFrame> {
self.shared(number).map(|frame| &**frame)
}
pub(crate) fn shared(&self, number: u64) -> Option<&Arc<CaptureFrame>> {
let index = number.checked_sub(self.first)?;
self.frames.get(usize::try_from(index).ok()?)
}
pub(crate) fn kept(&self) -> &VecDeque<u64> {
&self.kept
}
pub(crate) fn filter(&self) -> &Filter {
&self.filter
}
pub(crate) fn set_filter(&mut self, filter: Filter) {
self.filter = filter;
let first = self.first;
self.kept = self
.frames
.iter()
.zip(first..)
.filter(|(frame, _)| self.filter.matches(frame))
.map(|(_, number)| number)
.collect();
}
pub(crate) fn clear(&mut self) {
self.first = self.next();
self.frames.clear();
self.kept.clear();
}
}