use crate::{
EMLError, EMLErrorKind, NS_EML, NS_XAL,
common::{CountryNameCode, LocalityName},
io::{EMLElement, EMLElementReader, EMLElementWriter, QualifiedName, collect_struct},
};
#[derive(Debug, Clone)]
pub enum MinimalQualifyingAddress {
Locality(MinimalQualifyingAddressLocality),
Country(MinimalQualifyingAddressCountry),
}
impl MinimalQualifyingAddress {
pub fn new_locality(locality_name: impl Into<LocalityName>) -> Self {
MinimalQualifyingAddress::Locality(MinimalQualifyingAddressLocality::new(
locality_name.into(),
))
}
pub fn new_country(
country_name_code: impl Into<CountryNameCode>,
locality_name: impl Into<LocalityName>,
) -> Self {
MinimalQualifyingAddress::Country(MinimalQualifyingAddressCountry::new(
country_name_code.into(),
MinimalQualifyingAddressLocality::new(locality_name.into()),
))
}
}
impl EMLElement for MinimalQualifyingAddress {
const EML_NAME: QualifiedName<'_, '_> =
QualifiedName::from_static("QualifyingAddress", Some(NS_EML));
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
let parent_name = elem.name()?.as_owned();
let mut found_child = None;
while let Some(mut child) = elem.next_child()? {
match child.name()? {
n if n == MinimalQualifyingAddressLocality::EML_NAME && found_child.is_none() => {
found_child = Some(MinimalQualifyingAddress::Locality(
MinimalQualifyingAddressLocality::read_eml(&mut child)?,
));
}
n if n == MinimalQualifyingAddressCountry::EML_NAME && found_child.is_none() => {
found_child = Some(MinimalQualifyingAddress::Country(
MinimalQualifyingAddressCountry::read_eml(&mut child)?,
));
}
n => {
let span = child.span();
let name = n.as_owned();
let err =
EMLErrorKind::UnexpectedElement(name, parent_name.clone()).with_span(span);
if child.parsing_mode().is_strict() {
return Err(err);
} else {
child.push_err(err);
}
}
}
}
let Some(result) = found_child else {
return Err(EMLErrorKind::MissingChoiceElements(vec![
MinimalQualifyingAddressCountry::EML_NAME.as_owned(),
MinimalQualifyingAddressLocality::EML_NAME.as_owned(),
])
.with_span(elem.full_span()));
};
Ok(result)
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
let mut writer = writer.content()?;
match self {
MinimalQualifyingAddress::Locality(locality) => {
writer = writer.child_elem(MinimalQualifyingAddressLocality::EML_NAME, locality)?
}
MinimalQualifyingAddress::Country(country) => {
writer = writer.child_elem(MinimalQualifyingAddressCountry::EML_NAME, country)?
}
}
writer.finish()
}
}
#[derive(Debug, Clone)]
pub struct MinimalQualifyingAddressLocality {
pub locality_name: LocalityName,
}
impl MinimalQualifyingAddressLocality {
pub fn new(locality_name: LocalityName) -> Self {
MinimalQualifyingAddressLocality { locality_name }
}
}
impl EMLElement for MinimalQualifyingAddressLocality {
const EML_NAME: QualifiedName<'_, '_> = QualifiedName::from_static("Locality", Some(NS_XAL));
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
Ok(collect_struct!(
elem,
MinimalQualifyingAddressLocality {
locality_name: LocalityName::EML_NAME => |elem| LocalityName::read_eml(elem)?,
}
))
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
writer
.child_elem(LocalityName::EML_NAME, &self.locality_name)?
.finish()
}
}
#[derive(Debug, Clone)]
pub struct MinimalQualifyingAddressCountry {
pub country_name_code: CountryNameCode,
pub locality: MinimalQualifyingAddressLocality,
}
impl MinimalQualifyingAddressCountry {
pub fn new(
country_name_code: CountryNameCode,
locality: MinimalQualifyingAddressLocality,
) -> Self {
MinimalQualifyingAddressCountry {
country_name_code,
locality,
}
}
}
impl EMLElement for MinimalQualifyingAddressCountry {
const EML_NAME: QualifiedName<'_, '_> = QualifiedName::from_static("Country", Some(NS_XAL));
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
Ok(collect_struct!(elem, MinimalQualifyingAddressCountry {
country_name_code: CountryNameCode::EML_NAME => |elem| CountryNameCode::read_eml(elem)?,
locality: MinimalQualifyingAddressLocality::EML_NAME => |elem| MinimalQualifyingAddressLocality::read_eml(elem)?,
}))
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
writer
.child_elem(CountryNameCode::EML_NAME, &self.country_name_code)?
.child_elem(MinimalQualifyingAddressLocality::EML_NAME, &self.locality)?
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::io::{EMLParsingMode, EMLRead as _, test_write_eml_element, test_xml_fragment};
#[test]
fn test_minimal_qualifying_address_construction() {
let locality_name = LocalityName::new("Amsterdam");
let locality =
MinimalQualifyingAddress::new_country(CountryNameCode::new("NL"), locality_name);
if let MinimalQualifyingAddress::Country(country) = locality {
assert_eq!(country.country_name_code.value, "NL");
assert_eq!(country.locality.locality_name.name, "Amsterdam");
} else {
panic!("Expected a country qualifying address");
}
let locality_name = LocalityName::new("Rotterdam");
let locality = MinimalQualifyingAddress::new_locality(locality_name);
if let MinimalQualifyingAddress::Locality(locality) = locality {
assert_eq!(locality.locality_name.name, "Rotterdam");
} else {
panic!("Expected a locality qualifying address");
}
}
#[test]
fn test_minimal_qualifying_address_country_parsing() {
let xml = test_xml_fragment(
r#"
<QualifyingAddress xmlns="urn:oasis:names:tc:evs:schema:eml" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
<xal:Country>
<xal:CountryNameCode>NL</xal:CountryNameCode>
<xal:Locality>
<xal:LocalityName>Amsterdam</xal:LocalityName>
</xal:Locality>
</xal:Country>
</QualifyingAddress>
"#,
);
let address = MinimalQualifyingAddress::parse_eml(&xml, EMLParsingMode::Strict).unwrap();
if let MinimalQualifyingAddress::Country(country) = &address {
assert_eq!(country.country_name_code.value, "NL");
assert_eq!(country.locality.locality_name.name, "Amsterdam");
} else {
panic!("Expected a country qualifying address");
}
let xml_output = test_write_eml_element(&address, &[NS_EML, NS_XAL]).unwrap();
assert_eq!(xml_output, xml);
}
#[test]
fn test_minimal_qualifying_address_locality_parsing() {
let xml = test_xml_fragment(
r#"
<QualifyingAddress xmlns="urn:oasis:names:tc:evs:schema:eml" xmlns:xal="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">
<xal:Locality>
<xal:LocalityName>Amsterdam</xal:LocalityName>
</xal:Locality>
</QualifyingAddress>
"#,
);
let address = MinimalQualifyingAddress::parse_eml(&xml, EMLParsingMode::Strict).unwrap();
if let MinimalQualifyingAddress::Locality(locality) = &address {
assert_eq!(locality.locality_name.name, "Amsterdam");
} else {
panic!("Expected a locality qualifying address");
}
let xml_output = test_write_eml_element(&address, &[NS_EML, NS_XAL]).unwrap();
assert_eq!(xml_output, xml);
}
}