mf_core/
history_manager.rs

1/// 历史记录结构体
2pub struct History<T: Clone> {
3    pub past: Vec<T>,
4    pub present: T,
5    pub future: Vec<T>,
6    pub latest_unfiltered: T,
7}
8
9impl<T: Clone> History<T> {
10    /// 创建新的历史记录
11    pub fn new(
12        past: Vec<T>,
13        present: T,
14        future: Vec<T>,
15    ) -> Self {
16        let latest_unfiltered = present.clone();
17        History { past, present, future, latest_unfiltered }
18    }
19}
20
21use crate::config::HistoryConfig;
22
23/// 历史管理器
24pub struct HistoryManager<T: Clone> {
25    config: HistoryConfig,
26    history: History<T>,
27}
28
29impl<T: Clone> HistoryManager<T> {
30    /// 创建新的历史管理器
31    pub fn new(
32        initial_state: T,
33        history_limit: Option<usize>,
34    ) -> Self {
35        let mut config = HistoryConfig::default();
36        if let Some(limit) = history_limit {
37            config.max_entries = limit;
38        }
39        Self::with_config(initial_state, config)
40    }
41
42    /// 使用配置创建历史管理器
43    pub fn with_config(
44        initial_state: T,
45        config: HistoryConfig,
46    ) -> Self {
47        HistoryManager {
48            config,
49            history: History::new(Vec::new(), initial_state, Vec::new()),
50        }
51    }
52    /// 获取当前状态
53    pub fn get_present(&self) -> T {
54        self.history.present.clone()
55    }
56    /// 获取历史记录
57    pub fn get_history(&self) -> &History<T> {
58        &self.history
59    }
60    /// 获取历史记录长度
61    pub fn get_history_length(&self) -> usize {
62        self.history.past.len() + self.history.future.len() + 1
63    }
64
65    /// 获取历史配置
66    pub fn get_config(&self) -> &HistoryConfig {
67        &self.config
68    }
69
70    /// 更新历史配置
71    pub fn update_config(
72        &mut self,
73        config: HistoryConfig,
74    ) {
75        self.config = config;
76    }
77    /// 插入新状态
78    ///
79    /// 当历史记录超出最大限制时,自动舍弃最旧的记录
80    pub fn insert(
81        &mut self,
82        state: T,
83    ) {
84        let past = &self.history.past;
85        let length = past.len() + 1;
86
87        // 处理历史长度限制:超出时舍弃第一个(最旧的)
88        let past_sliced = if length >= self.config.max_entries {
89            if past.is_empty() { Vec::new() } else { past[1..].to_vec() }
90        } else {
91            past.clone()
92        };
93
94        // 构建新的历史记录
95        let mut new_past = past_sliced;
96        new_past.push(self.history.latest_unfiltered.clone());
97
98        self.history = History::new(new_past, state.clone(), Vec::new());
99        self.history.latest_unfiltered = state;
100    }
101
102    /// 跳转到未来状态
103    ///
104    /// # 边界检查
105    /// - 检查索引是否在有效范围内
106    /// - 安全的数组切片操作
107    pub fn jump_to_future(
108        &mut self,
109        index: usize,
110    ) {
111        // 边界检查:确保索引有效
112        if index >= self.history.future.len() {
113            return;
114        }
115
116        // 安全的数组访问
117        let mut new_past = self.history.past.clone();
118        new_past.push(self.history.latest_unfiltered.clone());
119
120        // 安全地添加未来状态到过去
121        if index > 0 {
122            new_past.extend_from_slice(&self.history.future[..index]);
123        }
124
125        let new_present = self.history.future[index].clone();
126
127        // 安全地构建新的未来状态
128        let new_future = if index + 1 < self.history.future.len() {
129            self.history.future[index + 1..].to_vec()
130        } else {
131            Vec::new()
132        };
133
134        self.history = History::new(new_past, new_present, new_future);
135    }
136
137    /// 跳转到过去状态
138    ///
139    /// # 边界检查
140    /// - 检查索引是否在有效范围内
141    /// - 安全的数组切片操作
142    pub fn jump_to_past(
143        &mut self,
144        index: usize,
145    ) {
146        // 边界检查:确保索引有效
147        if index >= self.history.past.len() {
148            return;
149        }
150
151        // 安全地构建新的过去状态
152        let new_past = if index > 0 {
153            self.history.past[..index].to_vec()
154        } else {
155            Vec::new()
156        };
157
158        // 安全地构建新的未来状态
159        let mut new_future = Vec::new();
160
161        // 添加被跳过的过去状态到未来
162        if index + 1 < self.history.past.len() {
163            new_future.extend_from_slice(&self.history.past[index + 1..]);
164        }
165
166        // 添加当前状态到未来
167        new_future.push(self.history.latest_unfiltered.clone());
168
169        // 添加原有的未来状态
170        new_future.extend_from_slice(&self.history.future);
171
172        let new_present = self.history.past[index].clone();
173
174        self.history = History::new(new_past, new_present, new_future);
175    }
176
177    /// 通用跳转方法
178    ///
179    /// # 参数
180    /// - `n`: 跳转的步数
181    ///   - 负数:向过去跳转
182    ///   - 正数:向未来跳转
183    ///   - 0:不跳转
184    ///
185    /// # 边界检查
186    /// - 自动限制在有效范围内
187    /// - 超出范围的跳转会被忽略
188    pub fn jump(
189        &mut self,
190        n: isize,
191    ) {
192        match n.cmp(&0) {
193            std::cmp::Ordering::Less => {
194                // 向过去跳转
195                let past_len = self.history.past.len() as isize;
196                let target = past_len + n; // n 是负数,所以这是减法
197
198                // 边界检查:确保目标索引有效
199                if target >= 0 && (target as usize) < self.history.past.len() {
200                    self.jump_to_past(target as usize);
201                }
202                // 如果超出边界,静默忽略
203            },
204            std::cmp::Ordering::Equal => {
205                // 不跳转
206            },
207            std::cmp::Ordering::Greater => {
208                // 向未来跳转
209                let future_index = (n - 1) as usize; // -1 因为 n=1 表示跳到第一个未来状态
210
211                // 边界检查:确保未来索引有效
212                if future_index < self.history.future.len() {
213                    self.jump_to_future(future_index);
214                }
215                // 如果超出边界,静默忽略
216            },
217        }
218    }
219
220    /// 清空历史记录
221    pub fn clear_history(&mut self) {
222        let present = self.history.present.clone();
223        self.history = History::new(Vec::new(), present, Vec::new());
224    }
225
226    /// 安全地获取过去状态
227    ///
228    /// # 边界检查
229    /// - 返回 Option 以处理无效索引
230    pub fn get_past_state(
231        &self,
232        index: usize,
233    ) -> Option<&T> {
234        self.history.past.get(index)
235    }
236
237    /// 安全地获取未来状态
238    ///
239    /// # 边界检查
240    /// - 返回 Option 以处理无效索引
241    pub fn get_future_state(
242        &self,
243        index: usize,
244    ) -> Option<&T> {
245        self.history.future.get(index)
246    }
247
248    /// 检查是否可以撤销(向过去跳转)
249    pub fn can_undo(&self) -> bool {
250        !self.history.past.is_empty()
251    }
252
253    /// 检查是否可以重做(向未来跳转)
254    pub fn can_redo(&self) -> bool {
255        !self.history.future.is_empty()
256    }
257
258    /// 获取过去状态的数量
259    pub fn past_count(&self) -> usize {
260        self.history.past.len()
261    }
262
263    /// 获取未来状态的数量
264    pub fn future_count(&self) -> usize {
265        self.history.future.len()
266    }
267
268    /// 验证历史记录的完整性
269    ///
270    /// 用于调试和测试,确保历史记录结构正确
271    pub fn validate_integrity(&self) -> bool {
272        // 检查配置是否合理
273        if self.config.max_entries == 0 {
274            return false;
275        }
276
277        // 检查总长度是否超出限制
278        let total_length =
279            self.history.past.len() + 1 + self.history.future.len();
280        if total_length > self.config.max_entries {
281            return false;
282        }
283
284        true
285    }
286}
287
288#[cfg(test)]
289mod tests {
290    use super::*;
291
292    #[test]
293    fn test_insert_with_limit() {
294        let mut manager = HistoryManager::with_config(
295            "initial".to_string(),
296            HistoryConfig { max_entries: 3, ..Default::default() },
297        );
298
299        // 插入状态,不应超出限制
300        manager.insert("state1".to_string());
301        manager.insert("state2".to_string());
302        manager.insert("state3".to_string()); // 这应该移除 "initial"
303
304        assert_eq!(manager.past_count(), 2); // state1, state2
305        assert_eq!(manager.get_present(), "state3");
306        assert!(manager.validate_integrity());
307    }
308
309    #[test]
310    fn test_jump_boundary_checks() {
311        let mut manager = HistoryManager::new("initial".to_string(), Some(10));
312
313        manager.insert("state1".to_string());
314        manager.insert("state2".to_string());
315
316        // 测试跳转到过去
317        manager.jump_to_past(0); // 应该跳转到 "initial"
318        assert_eq!(manager.get_present(), "initial");
319
320        // 测试无效的过去索引
321        manager.jump_to_past(100); // 应该被忽略
322        assert_eq!(manager.get_present(), "initial");
323
324        // 测试跳转到未来
325        manager.jump_to_future(0); // 应该跳转到 "state1"
326        assert_eq!(manager.get_present(), "state1");
327
328        // 测试无效的未来索引
329        manager.jump_to_future(100); // 应该被忽略
330        assert_eq!(manager.get_present(), "state1");
331    }
332
333    #[test]
334    fn test_safe_access_methods() {
335        let mut manager = HistoryManager::new("initial".to_string(), Some(10));
336        manager.insert("state1".to_string());
337        manager.insert("state2".to_string());
338
339        // 测试安全访问
340        assert_eq!(manager.get_past_state(0), Some(&"initial".to_string()));
341        assert_eq!(manager.get_past_state(100), None);
342
343        // 跳转到过去创建未来状态
344        manager.jump_to_past(0);
345        assert_eq!(manager.get_future_state(0), Some(&"state1".to_string()));
346        assert_eq!(manager.get_future_state(100), None);
347    }
348
349    #[test]
350    fn test_can_undo_redo() {
351        let mut manager = HistoryManager::new("initial".to_string(), Some(10));
352
353        // 初始状态不能撤销或重做
354        assert!(!manager.can_undo());
355        assert!(!manager.can_redo());
356
357        // 添加状态后可以撤销
358        manager.insert("state1".to_string());
359        assert!(manager.can_undo());
360        assert!(!manager.can_redo());
361
362        // 跳转到过去后可以重做
363        manager.jump_to_past(0);
364        assert!(!manager.can_undo());
365        assert!(manager.can_redo());
366    }
367
368    #[test]
369    fn test_jump_with_bounds() {
370        let mut manager = HistoryManager::new("initial".to_string(), Some(10));
371        manager.insert("state1".to_string());
372        manager.insert("state2".to_string());
373
374        // 测试通用跳转方法的边界检查
375        manager.jump(-10); // 超出过去边界,应该被忽略
376        assert_eq!(manager.get_present(), "state2");
377
378        manager.jump(-1); // 跳转到 state1
379        assert_eq!(manager.get_present(), "state1");
380
381        manager.jump(10); // 超出未来边界,应该被忽略
382        assert_eq!(manager.get_present(), "state1");
383
384        manager.jump(1); // 跳转到 state2
385        assert_eq!(manager.get_present(), "state2");
386    }
387}