tvdata_rs/scanner/
validation.rs1use crate::scanner::query::ScanQuery;
2use crate::scanner::{Column, Market};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct PartiallySupportedColumn {
6 pub column: Column,
7 pub supported_markets: Vec<Market>,
8 pub unsupported_markets: Vec<Market>,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct ScanValidationReport {
13 pub route_segment: String,
14 pub requested_markets: Vec<Market>,
15 pub supported_columns: Vec<Column>,
16 pub partially_supported_columns: Vec<PartiallySupportedColumn>,
17 pub unsupported_columns: Vec<Column>,
18}
19
20impl ScanValidationReport {
21 pub fn is_strictly_supported(&self) -> bool {
22 self.partially_supported_columns.is_empty() && self.unsupported_columns.is_empty()
23 }
24
25 pub fn is_leniently_supported(&self) -> bool {
26 self.unsupported_columns.is_empty()
27 }
28
29 pub fn strict_violation_column_names(&self) -> Vec<&str> {
30 self.partially_supported_columns
31 .iter()
32 .map(|entry| entry.column.as_str())
33 .chain(self.unsupported_columns.iter().map(Column::as_str))
34 .collect()
35 }
36
37 pub fn filtered_query(&self, query: &ScanQuery) -> ScanQuery {
38 let mut filtered = query.clone();
39 filtered.columns = self.supported_columns.clone();
40 filtered
41 }
42
43 pub fn filtered_column_names(&self) -> Vec<&str> {
44 self.supported_columns.iter().map(Column::as_str).collect()
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn report_distinguishes_strict_and_lenient_support() {
54 let report = ScanValidationReport {
55 route_segment: "global/scan".to_owned(),
56 requested_markets: vec![
57 Market::from_static("america"),
58 Market::from_static("crypto"),
59 ],
60 supported_columns: vec![Column::from_static("close")],
61 partially_supported_columns: vec![PartiallySupportedColumn {
62 column: Column::from_static("market_cap_basic"),
63 supported_markets: vec![Market::from_static("america")],
64 unsupported_markets: vec![Market::from_static("crypto")],
65 }],
66 unsupported_columns: vec![Column::from_static("imaginary_field")],
67 };
68
69 assert!(!report.is_strictly_supported());
70 assert!(!report.is_leniently_supported());
71 assert_eq!(
72 report.strict_violation_column_names(),
73 vec!["market_cap_basic", "imaginary_field"]
74 );
75 let filtered =
76 report.filtered_query(&ScanQuery::new().markets(["america", "crypto"]).select([
77 Column::from_static("close"),
78 Column::from_static("market_cap_basic"),
79 ]));
80 assert_eq!(filtered.columns, vec![Column::from_static("close")]);
81 }
82}