use std::collections::VecDeque;
use super::{CommandRecord, CommandRecordFinish, CommandRecordStart};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct CommandRecordId(u64);
impl CommandRecordId {
#[must_use]
pub const fn get(self) -> u64 {
self.0
}
}
#[derive(Clone, Debug)]
pub struct CommandHistory {
records: VecDeque<CommandRecord>,
limit: usize,
next_id: u64,
}
impl CommandHistory {
#[must_use]
pub const fn new(limit: usize) -> Self {
Self {
records: VecDeque::new(),
limit,
next_id: 1,
}
}
#[must_use]
pub const fn limit(&self) -> usize {
self.limit
}
pub fn start(&mut self, input: CommandRecordStart) -> PendingCommandRecord {
let id = self.allocate_id();
let record = CommandRecord::started(id, input);
self.push_record(record);
PendingCommandRecord { id }
}
pub fn finish(&mut self, pending: &PendingCommandRecord, finish: CommandRecordFinish) -> bool {
if let Some(record) = self
.records
.iter_mut()
.find(|record| record.id == pending.id)
{
return record.finish(finish);
}
false
}
pub fn append(
&mut self,
input: CommandRecordStart,
finish: CommandRecordFinish,
) -> CommandRecordId {
let pending = self.start(input);
let id = pending.id;
self.finish(&pending, finish);
id
}
#[must_use]
pub fn records(&self) -> impl DoubleEndedIterator<Item = &CommandRecord> {
self.records.iter()
}
const fn allocate_id(&mut self) -> CommandRecordId {
let id = CommandRecordId(self.next_id);
self.next_id += 1;
id
}
fn push_record(&mut self, record: CommandRecord) {
if self.limit == 0 {
return;
}
while self.records.len() >= self.limit {
self.records.pop_front();
}
self.records.push_back(record);
}
}
impl Default for CommandHistory {
fn default() -> Self {
Self::new(128)
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct PendingCommandRecord {
id: CommandRecordId,
}
impl PendingCommandRecord {
#[must_use]
pub const fn id(&self) -> CommandRecordId {
self.id
}
}