use edifact_rs::OwnedSegment;
use crate::{DvgwMessageType, DvgwVersion};
pub(crate) fn find_segment<'a>(segs: &'a [OwnedSegment], tag: &str) -> Option<&'a OwnedSegment> {
segs.iter().find(|s| s.tag == tag)
}
pub(crate) fn find_all_segments<'a>(
segs: &'a [OwnedSegment],
tag: &str,
) -> impl Iterator<Item = &'a OwnedSegment> {
segs.iter().filter(move |s| s.tag == tag)
}
pub(crate) fn extract_message_ref(segs: &[OwnedSegment]) -> &str {
segs.iter()
.find(|s| s.tag == "UNH")
.and_then(|s| s.element_str(0))
.unwrap_or("")
}
pub(crate) fn extract_version(segs: &[OwnedSegment]) -> Option<DvgwVersion> {
let unh = segs.iter().find(|s| s.tag == "UNH")?;
let assoc = unh.component_str(1, 4)?;
DvgwVersion::parse(assoc)
}
pub(crate) fn extract_message_type_code(segs: &[OwnedSegment]) -> Option<String> {
let unh = segs.iter().find(|s| s.tag == "UNH")?;
Some(unh.component_str(1, 0)?.to_owned())
}
pub trait DvgwMessage: Send + Sync {
fn message_type(&self) -> DvgwMessageType;
fn version(&self) -> Option<&DvgwVersion>;
fn message_ref(&self) -> &str;
fn sender_eic(&self) -> Option<&str>;
fn receiver_eic(&self) -> Option<&str>;
fn segments(&self) -> &[OwnedSegment];
}
#[derive(Debug, Clone)]
pub(crate) struct MessageCore {
pub(crate) segments: Vec<OwnedSegment>,
pub(crate) message_type: DvgwMessageType,
pub(crate) version: Option<DvgwVersion>,
pub(crate) message_ref: String,
pub(crate) sender_eic: Option<String>,
pub(crate) receiver_eic: Option<String>,
}
impl MessageCore {
pub(crate) fn from_segments(
segments: Vec<OwnedSegment>,
message_type: DvgwMessageType,
) -> Self {
let version = extract_version(&segments);
let message_ref = extract_message_ref(&segments).to_owned();
let sender_eic = extract_nad_eic(&segments, "MS");
let receiver_eic = extract_nad_eic(&segments, "MR");
Self {
segments,
message_type,
version,
message_ref,
sender_eic,
receiver_eic,
}
}
}
fn extract_nad_eic(segs: &[OwnedSegment], qualifier: &str) -> Option<String> {
segs.iter()
.find(|s| s.tag == "NAD" && s.element_str(0) == Some(qualifier))
.and_then(|s| s.component_str(1, 0))
.map(str::to_owned)
}
macro_rules! impl_dvgw_message {
($T:ty) => {
impl crate::message::DvgwMessage for $T {
fn message_type(&self) -> crate::DvgwMessageType {
self.core.message_type
}
fn version(&self) -> Option<&crate::DvgwVersion> {
self.core.version.as_ref()
}
fn message_ref(&self) -> &str {
&self.core.message_ref
}
fn sender_eic(&self) -> Option<&str> {
self.core.sender_eic.as_deref()
}
fn receiver_eic(&self) -> Option<&str> {
self.core.receiver_eic.as_deref()
}
fn segments(&self) -> &[edifact_rs::OwnedSegment] {
&self.core.segments
}
}
};
}
pub(crate) use impl_dvgw_message;