ocpi_tariffs/lint/
tariff.rs1#[cfg(test)]
2mod test;
3
4pub(crate) mod v211;
5pub(crate) mod v221;
6pub mod v2x;
7
8use std::{borrow::Cow, fmt};
9
10use crate::{
11 country, currency, datetime, from_warning_all, json, money, number, string, tariff, warning,
12 Versioned as _,
13};
14
15pub(crate) fn lint(tariff: &tariff::Versioned<'_>) -> Report {
20 let mut warnings = warning::Set::new();
21
22 {
23 let walker = json::walk::DepthFirst::new(tariff.as_element());
27
28 for elem in walker.filter(|&elem| elem.value().is_null()) {
29 warnings.insert(Warning::NeedlessNullField, elem);
30 }
31 }
32
33 match tariff.version() {
34 crate::Version::V221 => v221::lint(tariff.as_element(), warnings),
35 crate::Version::V211 => v211::lint(tariff.as_element(), warnings),
36 }
37}
38
39#[derive(Debug)]
41pub struct Report {
42 pub warnings: warning::Set<Warning>,
44}
45
46#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
47pub enum Warning {
48 Country(country::Warning),
49
50 CpoCountryCodeShouldBeAlpha2,
52
53 Currency(currency::Warning),
54
55 DateTime(datetime::Warning),
56
57 Elements(v2x::elements::Warning),
58
59 FieldRequired {
61 field_name: Cow<'static, str>,
62 },
63
64 MinPriceIsGreaterThanMax,
66
67 Money(money::Warning),
68
69 NeedlessNullField,
71
72 Number(number::Warning),
73
74 String(string::Warning),
75
76 StartDateTimeIsAfterEndDateTime,
78}
79
80from_warning_all!(
81 country::Warning => Warning::Country,
82 currency::Warning => Warning::Currency,
83 datetime::Warning => Warning::DateTime,
84 number::Warning => Warning::Number,
85 money::Warning => Warning::Money,
86 string::Warning => Warning::String,
87 v2x::elements::Warning => Warning::Elements
88);
89
90impl crate::Warning for Warning {
91 fn id(&self) -> warning::Id {
92 match self {
93 Self::CpoCountryCodeShouldBeAlpha2 => {
94 warning::Id::from_static("cpo_country_code_should_be_alpha2")
95 }
96 Self::Country(kind) => kind.id(),
97 Self::Currency(kind) => kind.id(),
98 Self::DateTime(kind) => kind.id(),
99 Self::Elements(kind) => kind.id(),
100 Self::FieldRequired { field_name } => {
101 warning::Id::from_string(format!("field_required({field_name})"))
102 }
103 Self::MinPriceIsGreaterThanMax => {
104 warning::Id::from_static("min_price_is_greater_than_max")
105 }
106 Self::Money(kind) => kind.id(),
107 Self::NeedlessNullField => warning::Id::from_static("needless_null_field"),
108 Self::Number(kind) => kind.id(),
109 Self::StartDateTimeIsAfterEndDateTime => {
110 warning::Id::from_static("start_date_time_is_after_end_date_time")
111 }
112 Self::String(kind) => kind.id(),
113 }
114 }
115}
116
117impl fmt::Display for Warning {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 match self {
120 Self::CpoCountryCodeShouldBeAlpha2 => {
121 f.write_str("The value should be an alpha-2 ISO 3166-1 country code")
122 }
123 Self::Country(kind) => fmt::Display::fmt(kind, f),
124 Self::Currency(kind) => fmt::Display::fmt(kind, f),
125 Self::DateTime(kind) => fmt::Display::fmt(kind, f),
126 Self::Elements(kind) => fmt::Display::fmt(kind, f),
127 Self::FieldRequired { field_name } => {
128 write!(f, "Field is required: `{field_name}`")
129 }
130 Self::MinPriceIsGreaterThanMax => {
131 f.write_str("The `min_price` is greater than `max_price`.")
132 }
133 Self::Money(kind) => fmt::Display::fmt(kind, f),
134 Self::NeedlessNullField => write!(f, "Null field: the field can simply be removed."),
135 Self::Number(kind) => fmt::Display::fmt(kind, f),
136 Self::StartDateTimeIsAfterEndDateTime => {
137 f.write_str("The `start_date_time` is after the `end_date_time`.")
138 }
139 Self::String(kind) => fmt::Display::fmt(kind, f),
140 }
141 }
142}