use crate::core::{BusinessArea, Error};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct MxId {
pub business_area: BusinessArea,
pub functionality: String,
pub variant: String,
pub version: String,
}
impl MxId {
pub fn new(
business_area: BusinessArea,
functionality: impl Into<String>,
variant: impl Into<String>,
version: impl Into<String>,
) -> MxId {
MxId {
business_area,
functionality: functionality.into(),
variant: variant.into(),
version: version.into(),
}
}
pub fn message_name(&self) -> String {
format!(
"{}.{}.{}.{}",
self.business_area.code(),
self.functionality,
self.variant,
self.version
)
}
pub fn namespace(&self) -> String {
format!("urn:iso:std:iso:20022:tech:xsd:{}", self.message_name())
}
pub fn parse(s: &str) -> Result<MxId, Error> {
let candidate = s.rsplit(':').next().unwrap_or(s).trim();
let parts: Vec<&str> = candidate.split('.').collect();
if parts.len() != 4 {
return Err(Error::InvalidMxId(s.to_string()));
}
let area = BusinessArea::from_code(parts[0])
.ok_or_else(|| Error::UnknownBusinessArea(parts[0].to_string()))?;
let valid = parts[0].len() == 4
&& parts[1].len() == 3
&& parts[2].len() == 3
&& parts[3].len() == 2
&& parts[1..].iter().all(|p| p.bytes().all(|b| b.is_ascii_digit()));
if !valid {
return Err(Error::InvalidMxId(s.to_string()));
}
Ok(MxId::new(area, parts[1], parts[2], parts[3]))
}
}
impl core::fmt::Display for MxId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(&self.message_name())
}
}
impl core::str::FromStr for MxId {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
MxId::parse(s)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for MxId {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&self.message_name())
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for MxId {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let s = String::deserialize(deserializer)?;
MxId::parse(&s).map_err(serde::de::Error::custom)
}
}