ddex_parser/streaming/
element.rs1use ddex_core::models::graph::*;
5use ddex_core::models::versions::ERNVersion;
6use ddex_core::models::Identifier;
7
8#[derive(Debug, Clone)]
10pub enum ParsedElement {
11 Header {
13 sender: MessageSender,
14 recipients: Vec<MessageRecipient>,
15 message_id: Identifier,
16 created_date_time: String,
17 version: ERNVersion,
18 },
19 Release(Release),
21 Resource(Resource),
23 Party(Party),
25 Deal(Deal),
27 EndOfStream,
29}
30
31impl ParsedElement {
32 pub fn element_type(&self) -> &'static str {
34 match self {
35 ParsedElement::Header { .. } => "Header",
36 ParsedElement::Release(_) => "Release",
37 ParsedElement::Resource(_) => "Resource",
38 ParsedElement::Party(_) => "Party",
39 ParsedElement::Deal(_) => "Deal",
40 ParsedElement::EndOfStream => "EndOfStream",
41 }
42 }
43
44 pub fn memory_estimate(&self) -> usize {
46 match self {
47 ParsedElement::Header { .. } => std::mem::size_of::<MessageHeader>() + 1024,
48 ParsedElement::Release(r) => estimate_release_size(r),
49 ParsedElement::Resource(r) => estimate_resource_size(r),
50 ParsedElement::Party(p) => estimate_party_size(p),
51 ParsedElement::Deal(d) => estimate_deal_size(d),
52 ParsedElement::EndOfStream => std::mem::size_of::<ParsedElement>(),
53 }
54 }
55
56 pub fn reference_id(&self) -> Option<&str> {
58 match self {
59 ParsedElement::Release(r) => Some(&r.release_reference),
60 ParsedElement::Resource(r) => Some(&r.resource_reference),
61 ParsedElement::Party(p) => p.party_id.first().map(|id| id.value.as_str()),
62 ParsedElement::Deal(d) => d.deal_reference.as_deref(),
63 _ => None,
64 }
65 }
66
67 pub fn is_complete(&self) -> bool {
69 match self {
70 ParsedElement::Header {
71 sender, message_id, ..
72 } => !sender.party_name.is_empty() && !message_id.value.is_empty(),
73 ParsedElement::Release(r) => {
74 !r.release_reference.is_empty() && !r.release_title.is_empty()
75 }
76 ParsedElement::Resource(r) => {
77 !r.resource_reference.is_empty() && !r.reference_title.is_empty()
78 }
79 ParsedElement::Party(p) => !p.party_id.is_empty() && !p.party_name.is_empty(),
80 ParsedElement::Deal(d) => d.deal_reference.as_ref().is_some_and(|r| !r.is_empty()),
81 ParsedElement::EndOfStream => true,
82 }
83 }
84}
85
86fn estimate_release_size(release: &Release) -> usize {
88 let mut size = std::mem::size_of::<Release>();
89 size += release.release_reference.len();
90 size += release.release_id.len() * std::mem::size_of::<Identifier>();
91 size += release.release_title.len() * 100; size += release.display_artist.len() * std::mem::size_of::<Artist>();
93 size += release
94 .genre
95 .iter()
96 .map(|g| g.genre_text.len())
97 .sum::<usize>();
98 size += release.release_resource_reference_list.len()
99 * std::mem::size_of::<ReleaseResourceReference>();
100 size
101}
102
103fn estimate_resource_size(resource: &Resource) -> usize {
105 let mut size = std::mem::size_of::<Resource>();
106 size += resource.resource_reference.len();
107 size += std::mem::size_of::<ResourceType>();
108 size += resource.resource_id.len() * std::mem::size_of::<Identifier>();
109 size += resource.reference_title.len() * 100; size
111}
112
113fn estimate_party_size(party: &Party) -> usize {
115 let mut size = std::mem::size_of::<Party>();
116 size += party
117 .party_id
118 .iter()
119 .map(|id| id.value.len())
120 .sum::<usize>();
121 size += party.party_name.len() * 100; size += party.party_id.len() * std::mem::size_of::<Identifier>();
123 size
124}
125
126fn estimate_deal_size(deal: &Deal) -> usize {
128 let mut size = std::mem::size_of::<Deal>();
129 size += deal.deal_reference.as_ref().map_or(0, |r| r.len());
130 size +=
131 deal.deal_terms.commercial_model_type.len() * std::mem::size_of::<CommercialModelType>();
132 size += deal.deal_terms.use_type.len() * std::mem::size_of::<UseType>();
133 size += deal
134 .deal_terms
135 .territory_code
136 .iter()
137 .map(|t| t.len())
138 .sum::<usize>();
139 size += std::mem::size_of::<DealTerms>();
141 size
142}
143
144#[derive(Debug, Default)]
146pub struct HeaderBuilder {
147 sender: Option<MessageSender>,
148 recipients: Vec<MessageRecipient>,
149 message_id: Option<Identifier>,
150 created_date_time: Option<String>,
151 version: Option<ERNVersion>,
152}
153
154impl HeaderBuilder {
155 pub fn new() -> Self {
156 Self::default()
157 }
158
159 pub fn sender(mut self, sender: MessageSender) -> Self {
160 self.sender = Some(sender);
161 self
162 }
163
164 pub fn add_recipient(mut self, recipient: MessageRecipient) -> Self {
165 self.recipients.push(recipient);
166 self
167 }
168
169 pub fn message_id(mut self, id: Identifier) -> Self {
170 self.message_id = Some(id);
171 self
172 }
173
174 pub fn created_date_time(mut self, datetime: String) -> Self {
175 self.created_date_time = Some(datetime);
176 self
177 }
178
179 pub fn version(mut self, version: ERNVersion) -> Self {
180 self.version = Some(version);
181 self
182 }
183
184 pub fn build(self) -> Result<ParsedElement, String> {
185 let sender = self.sender.ok_or("Missing sender")?;
186 let message_id = self.message_id.ok_or("Missing message ID")?;
187 let created_date_time = self.created_date_time.ok_or("Missing created date time")?;
188 let version = self.version.ok_or("Missing version")?;
189
190 Ok(ParsedElement::Header {
191 sender,
192 recipients: self.recipients,
193 message_id,
194 created_date_time,
195 version,
196 })
197 }
198}