Skip to main content

dsfb_semiconductor/input/
alarm_stream.rs

1#[cfg(not(feature = "std"))]
2use alloc::{string::String, vec::Vec};
3
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub struct AlarmSample {
8    pub timestamp: f64,
9    pub source: String,
10    pub active: bool,
11}
12
13#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
14pub struct AlarmStream {
15    samples: Vec<AlarmSample>,
16}
17
18impl AlarmStream {
19    pub fn new(mut samples: Vec<AlarmSample>) -> Self {
20        samples.sort_by(|left, right| {
21            left.timestamp
22                .total_cmp(&right.timestamp)
23                .then_with(|| left.source.cmp(&right.source))
24        });
25        Self { samples }
26    }
27
28    pub fn from_samples(samples: &[AlarmSample]) -> Self {
29        Self::new(samples.to_vec())
30    }
31
32    pub fn push_clone(&mut self, sample: &AlarmSample) {
33        self.samples.push(sample.clone());
34        self.samples.sort_by(|left, right| {
35            left.timestamp
36                .total_cmp(&right.timestamp)
37                .then_with(|| left.source.cmp(&right.source))
38        });
39    }
40
41    pub fn samples(&self) -> &[AlarmSample] {
42        &self.samples
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn alarm_stream_is_sorted_deterministically() {
52        let stream = AlarmStream::new(vec![
53            AlarmSample {
54                timestamp: 5.0,
55                source: "ewma".into(),
56                active: true,
57            },
58            AlarmSample {
59                timestamp: 1.0,
60                source: "threshold".into(),
61                active: false,
62            },
63        ]);
64        assert_eq!(stream.samples()[0].timestamp, 1.0);
65        assert_eq!(stream.samples()[1].timestamp, 5.0);
66    }
67}