use crate::core::{from_xml, to_xml, BusinessArea, Error, MxId};
pub trait MxMessage: yaserde::YaSerialize + yaserde::YaDeserialize + Sized {
const BUSINESS_AREA: BusinessArea;
const FUNCTIONALITY: &'static str;
const VARIANT: &'static str;
const VERSION: &'static str;
const MESSAGE_NAME: &'static str;
const NAMESPACE: &'static str;
fn mx_id() -> MxId {
MxId::new(
Self::BUSINESS_AREA,
Self::FUNCTIONALITY,
Self::VARIANT,
Self::VERSION,
)
}
fn parse(xml: &str) -> Result<Self, Error> {
from_xml(xml)
}
fn parse_checked(xml: &str) -> Result<Self, Error> {
match detect(xml) {
Some(id) if id.message_name() == Self::MESSAGE_NAME => from_xml(xml),
Some(id) => Err(Error::InvalidMxId(format!(
"expected {}, found {}",
Self::MESSAGE_NAME,
id.message_name()
))),
None => Err(Error::InvalidMxId(
"no ISO 20022 namespace found in XML".to_string(),
)),
}
}
fn to_xml_string(&self) -> Result<String, Error> {
to_xml(self)
}
}
pub fn detect(xml: &str) -> Option<MxId> {
let mut first: Option<MxId> = None;
for token in xml.split(['"', '\'', '<', '>', ' ', '\t', '\n', '\r']) {
if !token.starts_with("urn:") {
continue;
}
if let Ok(id) = MxId::parse(token) {
if id.business_area != BusinessArea::head {
return Some(id);
}
first.get_or_insert(id);
}
}
first
}