message_history.rs

 1pub struct MessageHistory<T> {
 2    items: Vec<T>,
 3    current: Option<usize>,
 4}
 5
 6impl<T> Default for MessageHistory<T> {
 7    fn default() -> Self {
 8        MessageHistory {
 9            items: Vec::new(),
10            current: None,
11        }
12    }
13}
14
15impl<T> MessageHistory<T> {
16    pub fn push(&mut self, message: T) {
17        self.current.take();
18        self.items.push(message);
19    }
20
21    pub fn reset_position(&mut self) {
22        self.current.take();
23    }
24
25    pub fn prev(&mut self) -> Option<&T> {
26        if self.items.is_empty() {
27            return None;
28        }
29
30        let new_ix = self
31            .current
32            .get_or_insert(self.items.len())
33            .saturating_sub(1);
34
35        self.current = Some(new_ix);
36        self.items.get(new_ix)
37    }
38
39    pub fn next(&mut self) -> Option<&T> {
40        let current = self.current.as_mut()?;
41        *current += 1;
42
43        self.items.get(*current).or_else(|| {
44            self.current.take();
45            None
46        })
47    }
48
49    #[cfg(test)]
50    pub fn items(&self) -> &[T] {
51        &self.items
52    }
53}
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_prev_next() {
60        let mut history = MessageHistory::default();
61
62        // Test empty history
63        assert_eq!(history.prev(), None);
64        assert_eq!(history.next(), None);
65
66        // Add some messages
67        history.push("first");
68        history.push("second");
69        history.push("third");
70
71        // Test prev navigation
72        assert_eq!(history.prev(), Some(&"third"));
73        assert_eq!(history.prev(), Some(&"second"));
74        assert_eq!(history.prev(), Some(&"first"));
75        assert_eq!(history.prev(), Some(&"first"));
76
77        assert_eq!(history.next(), Some(&"second"));
78
79        // Test mixed navigation
80        history.push("fourth");
81        assert_eq!(history.prev(), Some(&"fourth"));
82        assert_eq!(history.prev(), Some(&"third"));
83        assert_eq!(history.next(), Some(&"fourth"));
84        assert_eq!(history.next(), None);
85
86        // Test that push resets navigation
87        history.prev();
88        history.prev();
89        history.push("fifth");
90        assert_eq!(history.prev(), Some(&"fifth"));
91    }
92}