Skip to main content

dsfb_semiconductor/input/
residual_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 ResidualSample {
8    pub timestamp: f64,
9    pub feature_id: String,
10    pub value: f64,
11}
12
13#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
14pub struct ResidualStream {
15    samples: Vec<ResidualSample>,
16}
17
18impl ResidualStream {
19    pub fn new(mut samples: Vec<ResidualSample>) -> Self {
20        samples.sort_by(|left, right| {
21            left.timestamp
22                .total_cmp(&right.timestamp)
23                .then_with(|| left.feature_id.cmp(&right.feature_id))
24        });
25        Self { samples }
26    }
27
28    pub fn from_samples(samples: &[ResidualSample]) -> Self {
29        Self::new(samples.to_vec())
30    }
31
32    pub fn push_clone(&mut self, sample: &ResidualSample) {
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.feature_id.cmp(&right.feature_id))
38        });
39    }
40
41    pub fn samples(&self) -> &[ResidualSample] {
42        &self.samples
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn residual_stream_is_sorted_deterministically() {
52        let stream = ResidualStream::new(vec![
53            ResidualSample {
54                timestamp: 2.0,
55                feature_id: "S002".into(),
56                value: 1.0,
57            },
58            ResidualSample {
59                timestamp: 1.0,
60                feature_id: "S003".into(),
61                value: 1.0,
62            },
63            ResidualSample {
64                timestamp: 1.0,
65                feature_id: "S001".into(),
66                value: 1.0,
67            },
68        ]);
69        assert_eq!(stream.samples()[0].feature_id, "S001");
70        assert_eq!(stream.samples()[1].feature_id, "S003");
71        assert_eq!(stream.samples()[2].feature_id, "S002");
72    }
73}