Line data Source code
1 : //! A heapless buffer for events of sorts.
2 :
3 : use std::ops;
4 :
5 : use heapless::HistoryBuffer;
6 :
7 : #[derive(Debug, Clone)]
8 : pub struct HistoryBufferWithDropCounter<T, const L: usize> {
9 : buffer: HistoryBuffer<T, L>,
10 : drop_count: u64,
11 : }
12 :
13 : impl<T, const L: usize> HistoryBufferWithDropCounter<T, L> {
14 426524 : pub fn write(&mut self, data: T) {
15 426524 : let len_before = self.buffer.len();
16 426524 : self.buffer.write(data);
17 426524 : let len_after = self.buffer.len();
18 426524 : self.drop_count += u64::from(len_before == len_after);
19 426524 : }
20 24 : pub fn drop_count(&self) -> u64 {
21 24 : self.drop_count
22 24 : }
23 6 : pub fn map<U, F: Fn(&T) -> U>(&self, f: F) -> HistoryBufferWithDropCounter<U, L> {
24 6 : let mut buffer = HistoryBuffer::new();
25 6 : buffer.extend(self.buffer.oldest_ordered().map(f));
26 6 : HistoryBufferWithDropCounter::<U, L> {
27 6 : buffer,
28 6 : drop_count: self.drop_count,
29 6 : }
30 6 : }
31 : }
32 :
33 : impl<T, const L: usize> Default for HistoryBufferWithDropCounter<T, L> {
34 6280 : fn default() -> Self {
35 6280 : Self {
36 6280 : buffer: HistoryBuffer::default(),
37 6280 : drop_count: 0,
38 6280 : }
39 6280 : }
40 : }
41 :
42 : impl<T, const L: usize> ops::Deref for HistoryBufferWithDropCounter<T, L> {
43 : type Target = HistoryBuffer<T, L>;
44 :
45 26 : fn deref(&self) -> &Self::Target {
46 26 : &self.buffer
47 26 : }
48 : }
49 :
50 8 : #[derive(serde::Serialize, serde::Deserialize)]
51 : struct SerdeRepr<T> {
52 : buffer: Vec<T>,
53 : buffer_size: usize,
54 : drop_count: u64,
55 : }
56 :
57 : impl<'a, T, const L: usize> From<&'a HistoryBufferWithDropCounter<T, L>> for SerdeRepr<T>
58 : where
59 : T: Clone + serde::Serialize,
60 : {
61 2 : fn from(value: &'a HistoryBufferWithDropCounter<T, L>) -> Self {
62 2 : let HistoryBufferWithDropCounter { buffer, drop_count } = value;
63 2 : SerdeRepr {
64 2 : buffer: buffer.iter().cloned().collect(),
65 2 : buffer_size: L,
66 2 : drop_count: *drop_count,
67 2 : }
68 2 : }
69 : }
70 :
71 : impl<T, const L: usize> serde::Serialize for HistoryBufferWithDropCounter<T, L>
72 : where
73 : T: Clone + serde::Serialize,
74 : {
75 2 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
76 2 : where
77 2 : S: serde::Serializer,
78 2 : {
79 2 : SerdeRepr::from(self).serialize(serializer)
80 2 : }
81 : }
82 :
83 : impl<'de, T, const L: usize> serde::de::Deserialize<'de> for HistoryBufferWithDropCounter<T, L>
84 : where
85 : T: Clone + serde::Deserialize<'de>,
86 : {
87 2 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88 2 : where
89 2 : D: serde::Deserializer<'de>,
90 2 : {
91 : let SerdeRepr {
92 2 : buffer: des_buffer,
93 2 : drop_count,
94 2 : buffer_size,
95 2 : } = SerdeRepr::<T>::deserialize(deserializer)?;
96 2 : if buffer_size != L {
97 : use serde::de::Error;
98 0 : return Err(D::Error::custom(format!(
99 0 : "invalid buffer_size, expecting {L} got {buffer_size}"
100 0 : )));
101 2 : }
102 2 : let mut buffer = HistoryBuffer::new();
103 2 : buffer.extend(des_buffer);
104 2 : Ok(HistoryBufferWithDropCounter { buffer, drop_count })
105 2 : }
106 : }
107 :
108 : #[cfg(test)]
109 : mod test {
110 : use super::HistoryBufferWithDropCounter;
111 :
112 : #[test]
113 2 : fn test_basics() {
114 2 : let mut b = HistoryBufferWithDropCounter::<usize, 2>::default();
115 2 : b.write(1);
116 2 : b.write(2);
117 2 : b.write(3);
118 4 : assert!(b.iter().any(|e| *e == 2));
119 2 : assert!(b.iter().any(|e| *e == 3));
120 4 : assert!(!b.iter().any(|e| *e == 1));
121 :
122 : // round-trip serde
123 2 : let round_tripped: HistoryBufferWithDropCounter<usize, 2> =
124 2 : serde_json::from_str(&serde_json::to_string(&b).unwrap()).unwrap();
125 2 : assert_eq!(
126 2 : round_tripped.iter().cloned().collect::<Vec<_>>(),
127 2 : b.iter().cloned().collect::<Vec<_>>()
128 2 : );
129 2 : }
130 :
131 : #[test]
132 2 : fn test_drop_count_works() {
133 2 : let mut b = HistoryBufferWithDropCounter::<_, 2>::default();
134 2 : b.write(1);
135 2 : assert_eq!(b.drop_count(), 0);
136 2 : b.write(2);
137 2 : assert_eq!(b.drop_count(), 0);
138 2 : b.write(3);
139 2 : assert_eq!(b.drop_count(), 1);
140 2 : b.write(4);
141 2 : assert_eq!(b.drop_count(), 2);
142 2 : }
143 :
144 : #[test]
145 2 : fn test_clone_works() {
146 2 : let mut b = HistoryBufferWithDropCounter::<_, 2>::default();
147 2 : b.write(1);
148 2 : b.write(2);
149 2 : b.write(3);
150 2 : assert_eq!(b.drop_count(), 1);
151 2 : let mut c = b.clone();
152 2 : assert_eq!(c.drop_count(), 1);
153 4 : assert!(c.iter().any(|e| *e == 2));
154 2 : assert!(c.iter().any(|e| *e == 3));
155 4 : assert!(!c.iter().any(|e| *e == 1));
156 :
157 2 : c.write(4);
158 4 : assert!(c.iter().any(|e| *e == 4));
159 4 : assert!(!b.iter().any(|e| *e == 4));
160 2 : }
161 :
162 : #[test]
163 2 : fn test_map() {
164 2 : let mut b = HistoryBufferWithDropCounter::<_, 2>::default();
165 2 :
166 2 : b.write(1);
167 2 : assert_eq!(b.drop_count(), 0);
168 : {
169 2 : let c = b.map(|i| i + 10);
170 2 : assert_eq!(c.oldest_ordered().cloned().collect::<Vec<_>>(), vec![11]);
171 2 : assert_eq!(c.drop_count(), 0);
172 : }
173 :
174 2 : b.write(2);
175 2 : assert_eq!(b.drop_count(), 0);
176 : {
177 4 : let c = b.map(|i| i + 10);
178 2 : assert_eq!(
179 2 : c.oldest_ordered().cloned().collect::<Vec<_>>(),
180 2 : vec![11, 12]
181 2 : );
182 2 : assert_eq!(c.drop_count(), 0);
183 : }
184 :
185 2 : b.write(3);
186 2 : assert_eq!(b.drop_count(), 1);
187 : {
188 4 : let c = b.map(|i| i + 10);
189 2 : assert_eq!(
190 2 : c.oldest_ordered().cloned().collect::<Vec<_>>(),
191 2 : vec![12, 13]
192 2 : );
193 2 : assert_eq!(c.drop_count(), 1);
194 : }
195 2 : }
196 : }
|