gnss_qc_traits/processing/
decim.rs

1use crate::processing::{FilterItem, ItemError};
2use hifitime::Duration;
3use thiserror::Error;
4
5/// Decimation filter parsing error
6#[derive(Error, Debug)]
7pub enum Error {
8    #[error("invalid decimated item")]
9    InvalidDecimItem(#[from] ItemError),
10    #[error("failed to parse decimation attribute \"{0}\"")]
11    AttributeParsingError(String),
12}
13
14/// Type of decimation filter
15#[derive(Clone, Debug, PartialEq)]
16pub enum DecimationFilterType {
17    /// Simple modulo decimation
18    Modulo(u32),
19    /// Duration decimation
20    Duration(Duration),
21}
22
23#[derive(Clone, Debug, PartialEq)]
24pub struct DecimationFilter {
25    /// Type of decimation filter
26    pub filter: DecimationFilterType,
27    /// Optional decimated item.
28    /// When item is None, all data is to be decimated.
29    /// When item is specified, only that subset is to be decimated.
30    pub item: Option<FilterItem>,
31}
32
33impl DecimationFilter {
34    /// Builds a new Duration decimation filter
35    pub fn duration(dt: Duration) -> Self {
36        Self {
37            item: None,
38            filter: DecimationFilterType::Duration(dt),
39        }
40    }
41    /// Builds new Modulo decimation filter
42    pub fn modulo(modulo: u32) -> Self {
43        Self {
44            item: None,
45            filter: DecimationFilterType::Modulo(modulo),
46        }
47    }
48    /// Adds targetted item to be decimated
49    pub fn with_item(&self, item: FilterItem) -> Self {
50        let mut s = self.clone();
51        s.item = Some(item.clone());
52        s
53    }
54}
55
56/// The [Decimate] trait is implemented to reduce data rate prior analysis.
57pub trait Decimate {
58    /// Immutable decimation
59    fn decimate(&self, f: &DecimationFilter) -> Self;
60    /// Mutable decimation
61    fn decimate_mut(&mut self, f: &DecimationFilter);
62}
63
64impl std::str::FromStr for DecimationFilter {
65    type Err = Error;
66    fn from_str(content: &str) -> Result<Self, Self::Err> {
67        let items: Vec<&str> = content.trim().split(':').collect();
68        if let Ok(dt) = Duration::from_str(items[0].trim()) {
69            Ok(Self {
70                item: {
71                    if items.len() > 1 {
72                        let item = FilterItem::from_str(items[1].trim())?;
73                        Some(item)
74                    } else {
75                        None // no subset description
76                    }
77                },
78                filter: DecimationFilterType::Duration(dt),
79            })
80        } else if let Ok(r) = items[0].trim().parse::<u32>() {
81            Ok(Self {
82                item: {
83                    if items.len() > 1 {
84                        let item = FilterItem::from_str(items[1].trim())?;
85                        Some(item)
86                    } else {
87                        None
88                    }
89                },
90                filter: DecimationFilterType::Modulo(r),
91            })
92        } else {
93            Err(Error::AttributeParsingError(items[0].to_string()))
94        }
95    }
96}