use std::collections::VecDeque;
use std::fmt::{Debug, Display, Formatter};
use tick_id::TickId;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ItemInfo<T> {
pub item: T,
pub tick_id: TickId,
}
impl<T: Display> Display for ItemInfo<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.tick_id, self.item)
}
}
#[derive(Debug)]
pub struct Queue<T> {
items: VecDeque<ItemInfo<T>>,
expected_write_id: TickId, }
impl<T> Default for Queue<T> {
fn default() -> Self {
Self {
items: VecDeque::default(),
expected_write_id: TickId::default(),
}
}
}
impl<T> Queue<T> {
pub fn iter(&self) -> impl Iterator<Item = &ItemInfo<T>> {
self.items.iter()
}
}
impl<T> IntoIterator for Queue<T> {
type Item = ItemInfo<T>;
type IntoIter = std::collections::vec_deque::IntoIter<ItemInfo<T>>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
pub struct FromIndexIterator<'a, T> {
deque: &'a VecDeque<ItemInfo<T>>,
#[allow(unused)]
start_index: usize,
current_index: usize,
}
impl<'a, T> FromIndexIterator<'a, T> {
#[must_use]
pub const fn new(deque: &'a VecDeque<ItemInfo<T>>, start_index: usize) -> Self {
Self {
deque,
start_index,
current_index: start_index,
}
}
}
impl<T: Clone> Iterator for FromIndexIterator<'_, T> {
type Item = ItemInfo<T>;
fn next(&mut self) -> Option<Self::Item> {
let item = self.deque.get(self.current_index)?;
self.current_index += 1;
Some(item.clone())
}
}
pub const TICK_ID_MAX: u32 = u32::MAX;
#[derive(Debug)]
pub enum QueueError {
WrongTickId {
expected: TickId,
encountered: TickId,
},
}
impl<T: Clone> Queue<T> {
#[must_use]
pub const fn new(tick_id: TickId) -> Self {
Self {
items: VecDeque::new(),
expected_write_id: tick_id,
}
}
pub fn clear(&mut self, initial_tick_id: TickId) {
self.items.clear();
self.expected_write_id = initial_tick_id;
}
pub fn push(&mut self, tick_id: TickId, item: T) -> Result<(), QueueError> {
if self.expected_write_id != tick_id {
Err(QueueError::WrongTickId {
expected: self.expected_write_id,
encountered: tick_id,
})?;
}
self.push_internal(item);
Ok(())
}
fn push_internal(&mut self, item: T) {
let info = ItemInfo {
item,
tick_id: self.expected_write_id,
};
self.items.push_back(info);
self.expected_write_id += 1;
}
#[must_use]
pub fn debug_get(&self, index: usize) -> Option<&ItemInfo<T>> {
self.items.get(index)
}
#[must_use]
pub fn pop(&mut self) -> Option<ItemInfo<T>> {
self.items.pop_front()
}
pub fn discard_up_to(&mut self, tick_id: TickId) {
while let Some(info) = self.items.front() {
if info.tick_id >= tick_id {
break;
}
self.items.pop_front();
}
}
pub fn discard_count(&mut self, count: usize) {
if count >= self.items.len() {
self.items.clear();
} else {
self.items.drain(..count);
}
}
#[must_use]
pub fn take(&mut self, count: usize) -> Option<(TickId, Vec<T>)> {
let first_tick_id = self.front_tick_id()?;
let items_to_take: Vec<T> = self
.items
.drain(..count.min(self.items.len()))
.map(|item_info| item_info.item)
.collect();
Some((first_tick_id, items_to_take))
}
#[must_use]
pub fn front_tick_id(&self) -> Option<TickId> {
self.items.front().map(|item_info| item_info.tick_id)
}
#[must_use]
pub const fn expected_write_tick_id(&self) -> TickId {
self.expected_write_id
}
#[must_use]
pub fn back_tick_id(&self) -> Option<TickId> {
self.items.back().map(|item_info| item_info.tick_id)
}
#[must_use]
pub fn len(&self) -> usize {
self.items.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
#[must_use]
pub fn to_vec(&self) -> Vec<T> {
let (front_slice, back_slice) = self.items.as_slices();
front_slice
.iter()
.chain(back_slice.iter())
.map(|item_info| item_info.item.clone())
.collect()
}
#[must_use]
pub const fn iter_index(&self, start_index: usize) -> FromIndexIterator<T> {
FromIndexIterator::new(&self.items, start_index)
}
}