gnss_qc_traits/processing/
mod.rs1use std::str::FromStr;
3use thiserror::Error;
4
5mod item;
6pub use item::{FilterItem, ItemError};
7
8mod mask;
9pub use mask::{Error as MaskError, MaskFilter, MaskOperand, Masking};
10
11mod decim;
12pub use decim::{Decimate, DecimationFilter, DecimationFilterType, Error as DecimationError};
13
14mod split;
15pub use split::Split;
16
17mod time;
18pub use time::{TimeCorrection, TimeCorrectionError, TimeCorrectionsDB, Timeshift};
19
20pub trait Preprocessing: Masking + Decimate + Split + Timeshift {
23 fn filter(&self, filter: &Filter) -> Self
25 where
26 Self: Sized,
27 {
28 match filter {
29 Filter::Mask(f) => self.mask(f),
30 Filter::Decimation(f) => self.decimate(f),
31 }
32 }
33 fn filter_mut(&mut self, filter: &Filter) {
35 match filter {
36 Filter::Mask(f) => self.mask_mut(f),
37 Filter::Decimation(f) => self.decimate_mut(f),
38 }
39 }
40}
41
42#[derive(Debug, Copy, Clone)]
44pub enum Repair {
45 Zero,
49}
50
51pub trait RepairTrait {
52 fn repair(&self, r: Repair) -> Self;
53 fn repair_mut(&mut self, r: Repair);
54}
55
56#[derive(Error, Debug)]
57pub enum Error {
58 #[error("invalid filter")]
59 InvalidFilter,
60 #[error("unknown filter type \"{0}\"")]
61 UnknownFilterType(String),
62 #[error("invalid mask filter")]
63 MaskFilterParsing(#[from] MaskError),
64 #[error("invalid filter item")]
65 FilterItemError(#[from] ItemError),
66 #[error("invalid decimation filter")]
67 DecimationFilterParsing(#[from] DecimationError),
68}
69
70#[derive(Debug, Clone, PartialEq)]
74pub enum Filter {
75 Mask(MaskFilter),
77 Decimation(DecimationFilter),
79 }
82
83impl Filter {
84 pub fn mask(operand: MaskOperand, item: FilterItem) -> Self {
86 Self::Mask(MaskFilter { operand, item })
87 }
88 pub fn equals(item: &str) -> Result<Self, ItemError> {
91 let item = FilterItem::from_str(item)?;
92 Ok(Self::mask(MaskOperand::Equals, item))
93 }
94 pub fn not_equals(item: &str) -> Result<Self, ItemError> {
97 let item = FilterItem::from_str(item)?;
98 Ok(Self::mask(MaskOperand::NotEquals, item))
99 }
100 pub fn greater_than(item: &str) -> Result<Self, ItemError> {
103 let item = FilterItem::from_str(item)?;
104 Ok(Self::mask(MaskOperand::GreaterThan, item))
105 }
106 pub fn greater_equals(item: &str) -> Result<Self, ItemError> {
109 let item = FilterItem::from_str(item)?;
110 Ok(Self::mask(MaskOperand::GreaterEquals, item))
111 }
112 pub fn lower_equals(item: &str) -> Result<Self, ItemError> {
115 let item = FilterItem::from_str(item)?;
116 Ok(Self::mask(MaskOperand::LowerEquals, item))
117 }
118 pub fn lower_than(item: &str) -> Result<Self, ItemError> {
121 let item = FilterItem::from_str(item)?;
122 Ok(Self::mask(MaskOperand::LowerThan, item))
123 }
124}
125
126impl From<MaskFilter> for Filter {
127 fn from(mask: MaskFilter) -> Self {
128 Self::Mask(mask)
129 }
130}
131
132impl std::ops::Not for Filter {
133 type Output = Self;
134 fn not(self) -> Self {
135 match self {
136 Self::Mask(f) => Self::Mask(!f),
137 _ => self.clone(), }
139 }
140}
141
142impl From<DecimationFilter> for Filter {
143 fn from(decim: decim::DecimationFilter) -> Self {
144 Self::Decimation(decim)
145 }
146}
147
148impl std::str::FromStr for Filter {
149 type Err = Error;
150 fn from_str(content: &str) -> Result<Self, Self::Err> {
151 let items: Vec<&str> = content.split(':').collect();
152
153 let identifier = items[0].trim();
154 if identifier.eq("decim") {
155 let offset = 6; Ok(Self::Decimation(DecimationFilter::from_str(
157 content[offset..].trim(),
158 )?))
159 } else if identifier.eq("mask") {
160 let offset = 5; Ok(Self::Mask(MaskFilter::from_str(content[offset..].trim())?))
162 } else {
163 if let Ok(f) = MaskFilter::from_str(content.trim()) {
165 Ok(Self::Mask(f))
166 } else {
167 Err(Error::UnknownFilterType(content.to_string()))
168 }
169 }
170 }
171}
172
173#[cfg(test)]
174mod test {
175 use super::*;
176 use std::str::FromStr;
177 #[test]
178 fn from_str() {
179 for descriptor in [
183 "GPS",
184 "=GPS",
185 " != GPS",
186 "G08, G09, G10",
187 "=G08, G09, G10",
188 "!= GPS, GAL",
189 ">G08, G09",
190 "iode",
191 "iode,gps",
192 "iode,crs,gps",
193 "iode,crs",
194 ">2020-01-14T00:31:55 UTC",
195 ] {
196 assert!(
197 Filter::from_str(descriptor).is_ok(),
198 "Filter::from_str failed on \"{}\"",
199 descriptor
200 );
201 }
202 for desc in [
206 "decim:10",
207 "decim:10 min",
208 "decim:1 hour",
209 "decim:10 min:l1c",
210 "decim:1 hour:L1C,L2C,L3C",
211 ] {
212 let filt = Filter::from_str(desc);
213 assert!(filt.is_ok(), "Filter::from_str failed on \"{}\"", desc);
214 }
215 for desc in [
219 "smooth:mov:10 min",
220 "smooth:mov:1 hour",
221 "smooth:mov:1 hour:l1c",
222 "smooth:mov:10 min:clk",
223 "smooth:hatch",
224 "smooth:hatch:l1c",
225 ] {
226 let filt = Filter::from_str(desc);
227 assert!(filt.is_ok(), "Filter::from_str failed on \"{}\"", desc);
228 }
229 }
230}