use en16931::profiles;
use en16931::validation::profile::Profile;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Flavour {
Known {
profile: &'static str,
specification_id: String,
},
ForeignCius(String),
Unknown(Option<String>),
}
impl Flavour {
#[must_use]
pub fn profile(&self) -> Option<&'static Profile> {
match self {
Self::Known {
specification_id, ..
} => profiles::for_specification_id(specification_id),
_ => None,
}
}
#[must_use]
pub fn is_xrechnung(&self) -> bool {
matches!(self, Self::Known { profile, .. } if profile.starts_with("XRechnung"))
}
}
const EN16931_PREFIX: &str = "urn:cen.eu:en16931:2017";
#[must_use]
pub fn detect(specification_id: Option<&str>) -> Flavour {
let Some(raw) = specification_id else {
return Flavour::Unknown(None);
};
let id = raw.trim();
if id.is_empty() {
return Flavour::Unknown(Some(raw.to_owned()));
}
if let Some(p) = profiles::for_specification_id(id) {
return Flavour::Known {
profile: p.id,
specification_id: id.to_owned(),
};
}
if id.starts_with(EN16931_PREFIX) {
return Flavour::ForeignCius(id.to_owned());
}
Flavour::Unknown(Some(raw.to_owned()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_registry_ids_are_all_recognised() {
for p in profiles::ALL {
let f = detect(Some(p.specification_id));
assert_eq!(
f.profile().map(|q| q.id),
Some(p.id),
"{} did not detect back to itself",
p.id
);
}
}
#[test]
fn a_foreign_cius_is_not_unknown() {
let f = detect(Some(
"urn:cen.eu:en16931:2017#compliant#urn:fdc:nen.nl:nlcius:v1.0",
));
assert!(matches!(f, Flavour::ForeignCius(_)));
assert!(f.profile().is_none(), "no defensible default profile");
assert!(!f.is_xrechnung());
}
#[test]
fn nonsense_is_unknown_and_keeps_the_original() {
assert_eq!(
detect(Some("hello")),
Flavour::Unknown(Some("hello".into()))
);
assert_eq!(detect(Some(" ")), Flavour::Unknown(Some(" ".into())));
assert_eq!(detect(None), Flavour::Unknown(None));
}
#[test]
fn whitespace_does_not_change_the_claim() {
let padded = detect(Some(
"\n urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0 ",
));
assert!(padded.is_xrechnung());
}
}