history_buffer/
lib.rs

1use std::time;
2use std::{fmt, iter::DoubleEndedIterator, mem, vec::Vec};
3
4/// A "history buffer", similar to a write-only ring buffer of fixed length.
5///
6/// This buffer keeps a fixed number of elements. On write, the oldest element is overwritten.
7/// Thus, the buffer is useful to keep a history of values with some desired depth.
8pub struct HistoryBuffer<T> {
9    max_size: usize,
10    write_index: usize,
11    buffer: Vec<T>,
12    last_data_at: time::Instant,
13}
14
15impl<T> HistoryBuffer<T> {
16    /// Create a new buffer with a specified max depth.
17    pub fn new(max_size: usize) -> Self {
18        HistoryBuffer {
19            max_size,
20            write_index: 0,
21            buffer: Vec::with_capacity(max_size),
22            last_data_at: time::Instant::now(),
23        }
24    }
25
26    /// Checks if the buffer is empty.
27    pub fn is_empty(&self) -> bool {
28        self.buffer.len() == 0
29    }
30
31    /// Checks if the buffer is full, i.e. it has reached capacity.
32    pub fn is_full(&self) -> bool {
33        self.buffer.len() == self.max_size
34    }
35
36    /// The maximum number of elements the buffer can hold.
37    pub fn max_len(&self) -> usize {
38        self.max_size
39    }
40
41    /// The number of elements currently in the buffer.
42    pub fn len(&self) -> usize {
43        self.buffer.len()
44    }
45
46    /// Clear all values in the buffer.
47    pub fn clear(&mut self) {
48        self.write_index = 0;
49        self.buffer.clear();
50    }
51
52    /// Get the most recent value written to the buffer.
53    pub fn most_recent(&self) -> Option<&T> {
54        if self.is_empty() {
55            None
56        } else {
57            if self.write_index == 0 {
58                self.buffer.last()
59            } else {
60                Some(&self.buffer[self.write_index - 1])
61            }
62        }
63    }
64
65    /// Write a new value into the buffer, if it overwrites an old value it is returned.
66    pub fn write(&mut self, val: T) -> Option<T> {
67        let r = if self.is_full() {
68            Some(mem::replace(&mut self.buffer[self.write_index], val))
69        } else {
70            self.buffer.push(val);
71
72            None
73        };
74
75        self.write_index = (self.write_index.wrapping_add(1)) % self.max_size;
76        self.last_data_at = time::Instant::now();
77
78        r
79    }
80
81    /// How long was it since the last measurement.
82    pub fn duration_since_last_measurement(&self) -> Option<time::Duration> {
83        if !self.is_empty() {
84            let now = time::Instant::now();
85            Some(now.duration_since(self.last_data_at))
86        } else {
87            None
88        }
89    }
90
91    /// Get the entire buffer as unsorted.
92    pub fn all_unsorted(&self) -> &[T] {
93        &self.buffer
94    }
95
96    /// Get the entire in chronological order, starting with the oldest element.
97    pub fn all(&self) -> impl DoubleEndedIterator<Item = &T> {
98        let write_index = self.write_index;
99        self.buffer[write_index..]
100            .iter()
101            .chain(self.buffer[..write_index].iter())
102    }
103}
104
105impl<T> fmt::Debug for HistoryBuffer<T>
106where
107    T: fmt::Debug,
108{
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
110        f.debug_list().entries(self.all()).finish()
111    }
112}