jk_core/command_history/
history.rs1use std::collections::VecDeque;
2
3use super::{CommandRecord, CommandRecordFinish, CommandRecordStart};
4
5#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct CommandRecordId(u64);
8
9impl CommandRecordId {
10 #[must_use]
12 pub const fn get(self) -> u64 {
13 self.0
14 }
15}
16
17#[derive(Clone, Debug)]
19pub struct CommandHistory {
20 records: VecDeque<CommandRecord>,
21 limit: usize,
22 next_id: u64,
23}
24
25impl CommandHistory {
26 #[must_use]
28 pub const fn new(limit: usize) -> Self {
29 Self {
30 records: VecDeque::new(),
31 limit,
32 next_id: 1,
33 }
34 }
35
36 #[must_use]
38 pub const fn limit(&self) -> usize {
39 self.limit
40 }
41
42 pub fn start(&mut self, input: CommandRecordStart) -> PendingCommandRecord {
44 let id = self.allocate_id();
45 let record = CommandRecord::started(id, input);
46 self.push_record(record);
47 PendingCommandRecord { id }
48 }
49
50 pub fn finish(&mut self, pending: &PendingCommandRecord, finish: CommandRecordFinish) -> bool {
55 if let Some(record) = self
56 .records
57 .iter_mut()
58 .find(|record| record.id == pending.id)
59 {
60 return record.finish(finish);
61 }
62 false
63 }
64
65 pub fn append(
70 &mut self,
71 input: CommandRecordStart,
72 finish: CommandRecordFinish,
73 ) -> CommandRecordId {
74 let pending = self.start(input);
75 let id = pending.id;
76 self.finish(&pending, finish);
77 id
78 }
79
80 #[must_use]
82 pub fn records(&self) -> impl DoubleEndedIterator<Item = &CommandRecord> {
83 self.records.iter()
84 }
85
86 const fn allocate_id(&mut self) -> CommandRecordId {
87 let id = CommandRecordId(self.next_id);
88 self.next_id += 1;
89 id
90 }
91
92 fn push_record(&mut self, record: CommandRecord) {
93 if self.limit == 0 {
94 return;
95 }
96
97 while self.records.len() >= self.limit {
98 self.records.pop_front();
99 }
100 self.records.push_back(record);
101 }
102}
103
104impl Default for CommandHistory {
105 fn default() -> Self {
106 Self::new(128)
107 }
108}
109
110#[derive(Debug, Eq, PartialEq)]
112pub struct PendingCommandRecord {
113 id: CommandRecordId,
114}
115
116impl PendingCommandRecord {
117 #[must_use]
119 pub const fn id(&self) -> CommandRecordId {
120 self.id
121 }
122}