use ddex_core::models::graph::*;
use ddex_core::models::versions::ERNVersion;
use ddex_core::models::Identifier;
#[derive(Debug, Clone)]
pub enum ParsedElement {
Header {
sender: MessageSender,
recipients: Vec<MessageRecipient>,
message_id: Identifier,
created_date_time: String,
version: ERNVersion,
},
Release(Release),
Resource(Resource),
Party(Party),
Deal(Deal),
EndOfStream,
}
impl ParsedElement {
pub fn element_type(&self) -> &'static str {
match self {
ParsedElement::Header { .. } => "Header",
ParsedElement::Release(_) => "Release",
ParsedElement::Resource(_) => "Resource",
ParsedElement::Party(_) => "Party",
ParsedElement::Deal(_) => "Deal",
ParsedElement::EndOfStream => "EndOfStream",
}
}
pub fn memory_estimate(&self) -> usize {
match self {
ParsedElement::Header { .. } => std::mem::size_of::<MessageHeader>() + 1024,
ParsedElement::Release(r) => estimate_release_size(r),
ParsedElement::Resource(r) => estimate_resource_size(r),
ParsedElement::Party(p) => estimate_party_size(p),
ParsedElement::Deal(d) => estimate_deal_size(d),
ParsedElement::EndOfStream => std::mem::size_of::<ParsedElement>(),
}
}
pub fn reference_id(&self) -> Option<&str> {
match self {
ParsedElement::Release(r) => Some(&r.release_reference),
ParsedElement::Resource(r) => Some(&r.resource_reference),
ParsedElement::Party(p) => p.party_id.first().map(|id| id.value.as_str()),
ParsedElement::Deal(d) => d.deal_reference.as_deref(),
_ => None,
}
}
pub fn is_complete(&self) -> bool {
match self {
ParsedElement::Header {
sender, message_id, ..
} => !sender.party_name.is_empty() && !message_id.value.is_empty(),
ParsedElement::Release(r) => {
!r.release_reference.is_empty() && !r.release_title.is_empty()
}
ParsedElement::Resource(r) => {
!r.resource_reference.is_empty() && !r.reference_title.is_empty()
}
ParsedElement::Party(p) => !p.party_id.is_empty() && !p.party_name.is_empty(),
ParsedElement::Deal(d) => d.deal_reference.as_ref().is_some_and(|r| !r.is_empty()),
ParsedElement::EndOfStream => true,
}
}
}
fn estimate_release_size(release: &Release) -> usize {
let mut size = std::mem::size_of::<Release>();
size += release.release_reference.len();
size += release.release_id.len() * std::mem::size_of::<Identifier>();
size += release.release_title.len() * 100; size += release.display_artist.len() * std::mem::size_of::<Artist>();
size += release
.genre
.iter()
.map(|g| g.genre_text.len())
.sum::<usize>();
size += release.release_resource_reference_list.len()
* std::mem::size_of::<ReleaseResourceReference>();
size
}
fn estimate_resource_size(resource: &Resource) -> usize {
let mut size = std::mem::size_of::<Resource>();
size += resource.resource_reference.len();
size += std::mem::size_of::<ResourceType>();
size += resource.resource_id.len() * std::mem::size_of::<Identifier>();
size += resource.reference_title.len() * 100; size
}
fn estimate_party_size(party: &Party) -> usize {
let mut size = std::mem::size_of::<Party>();
size += party
.party_id
.iter()
.map(|id| id.value.len())
.sum::<usize>();
size += party.party_name.len() * 100; size += party.party_id.len() * std::mem::size_of::<Identifier>();
size
}
fn estimate_deal_size(deal: &Deal) -> usize {
let mut size = std::mem::size_of::<Deal>();
size += deal.deal_reference.as_ref().map_or(0, |r| r.len());
size +=
deal.deal_terms.commercial_model_type.len() * std::mem::size_of::<CommercialModelType>();
size += deal.deal_terms.use_type.len() * std::mem::size_of::<UseType>();
size += deal
.deal_terms
.territory_code
.iter()
.map(|t| t.len())
.sum::<usize>();
size += std::mem::size_of::<DealTerms>();
size
}
#[derive(Debug, Default)]
pub struct HeaderBuilder {
sender: Option<MessageSender>,
recipients: Vec<MessageRecipient>,
message_id: Option<Identifier>,
created_date_time: Option<String>,
version: Option<ERNVersion>,
}
impl HeaderBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn sender(mut self, sender: MessageSender) -> Self {
self.sender = Some(sender);
self
}
pub fn add_recipient(mut self, recipient: MessageRecipient) -> Self {
self.recipients.push(recipient);
self
}
pub fn message_id(mut self, id: Identifier) -> Self {
self.message_id = Some(id);
self
}
pub fn created_date_time(mut self, datetime: String) -> Self {
self.created_date_time = Some(datetime);
self
}
pub fn version(mut self, version: ERNVersion) -> Self {
self.version = Some(version);
self
}
pub fn build(self) -> Result<ParsedElement, String> {
let sender = self.sender.ok_or("Missing sender")?;
let message_id = self.message_id.ok_or("Missing message ID")?;
let created_date_time = self.created_date_time.ok_or("Missing created date time")?;
let version = self.version.ok_or("Missing version")?;
Ok(ParsedElement::Header {
sender,
recipients: self.recipients,
message_id,
created_date_time,
version,
})
}
}