#[cfg(test)]
mod test;
pub(crate) mod v211;
pub(crate) mod v221;
pub mod v2x;
use std::{borrow::Cow, fmt};
use crate::{
country, currency, datetime, from_warning_all, json, money, number, string, tariff, warning,
Versioned as _,
};
pub(crate) fn lint(tariff: &tariff::Versioned<'_>) -> Report {
let mut warnings = warning::Set::new();
{
let walker = json::walk::DepthFirst::new(tariff.as_element());
for elem in walker.filter(|&elem| elem.value().is_null()) {
warnings.insert(Warning::NeedlessNullField, elem);
}
}
match tariff.version() {
crate::Version::V221 => v221::lint(tariff.as_element(), warnings),
crate::Version::V211 => v211::lint(tariff.as_element(), warnings),
}
}
#[derive(Debug)]
pub struct Report {
pub warnings: warning::Set<Warning>,
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Warning {
Country(country::Warning),
CpoCountryCodeShouldBeAlpha2,
Currency(currency::Warning),
DateTime(datetime::Warning),
Elements(v2x::elements::Warning),
FieldRequired {
field_name: Cow<'static, str>,
},
MinPriceIsGreaterThanMax,
Money(money::Warning),
NeedlessNullField,
Number(number::Warning),
String(string::Warning),
StartDateTimeIsAfterEndDateTime,
}
from_warning_all!(
country::Warning => Warning::Country,
currency::Warning => Warning::Currency,
datetime::Warning => Warning::DateTime,
number::Warning => Warning::Number,
money::Warning => Warning::Money,
string::Warning => Warning::String,
v2x::elements::Warning => Warning::Elements
);
impl crate::Warning for Warning {
fn id(&self) -> warning::Id {
match self {
Self::CpoCountryCodeShouldBeAlpha2 => {
warning::Id::from_static("cpo_country_code_should_be_alpha2")
}
Self::Country(kind) => kind.id(),
Self::Currency(kind) => kind.id(),
Self::DateTime(kind) => kind.id(),
Self::Elements(kind) => kind.id(),
Self::FieldRequired { field_name } => {
warning::Id::from_string(format!("field_required({field_name})"))
}
Self::MinPriceIsGreaterThanMax => {
warning::Id::from_static("min_price_is_greater_than_max")
}
Self::Money(kind) => kind.id(),
Self::NeedlessNullField => warning::Id::from_static("needless_null_field"),
Self::Number(kind) => kind.id(),
Self::StartDateTimeIsAfterEndDateTime => {
warning::Id::from_static("start_date_time_is_after_end_date_time")
}
Self::String(kind) => kind.id(),
}
}
}
impl fmt::Display for Warning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::CpoCountryCodeShouldBeAlpha2 => {
f.write_str("The value should be an alpha-2 ISO 3166-1 country code")
}
Self::Country(kind) => fmt::Display::fmt(kind, f),
Self::Currency(kind) => fmt::Display::fmt(kind, f),
Self::DateTime(kind) => fmt::Display::fmt(kind, f),
Self::Elements(kind) => fmt::Display::fmt(kind, f),
Self::FieldRequired { field_name } => {
write!(f, "Field is required: `{field_name}`")
}
Self::MinPriceIsGreaterThanMax => {
f.write_str("The `min_price` is greater than `max_price`.")
}
Self::Money(kind) => fmt::Display::fmt(kind, f),
Self::NeedlessNullField => write!(f, "Null field: the field can simply be removed."),
Self::Number(kind) => fmt::Display::fmt(kind, f),
Self::StartDateTimeIsAfterEndDateTime => {
f.write_str("The `start_date_time` is after the `end_date_time`.")
}
Self::String(kind) => fmt::Display::fmt(kind, f),
}
}
}