LCOV - code coverage report
Current view: top level - libs/utils/src - history_buffer.rs (source / functions) Coverage Total Hit
Test: 465a86b0c1fda0069b3e0f6c1c126e6b635a1f72.info Lines: 97.6 % 124 121
Test Date: 2024-06-25 15:47:26 Functions: 46.7 % 75 35

            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       425980 :     pub fn write(&mut self, data: T) {
      15       425980 :         let len_before = self.buffer.len();
      16       425980 :         self.buffer.write(data);
      17       425980 :         let len_after = self.buffer.len();
      18       425980 :         self.drop_count += u64::from(len_before == len_after);
      19       425980 :     }
      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         6336 :     fn default() -> Self {
      35         6336 :         Self {
      36         6336 :             buffer: HistoryBuffer::default(),
      37         6336 :             drop_count: 0,
      38         6336 :         }
      39         6336 :     }
      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              : }
        

Generated by: LCOV version 2.1-beta