1use edifact_rs::OwnedSegment;
2
3use crate::{
4 CustomRulePack, EdiEnergyMessage, EdiEnergyReport, Error, MessageType, Pruefidentifikator,
5 Release,
6};
7
8#[cfg(feature = "aperak")]
9use crate::messages::aperak::AperakMessage;
10#[cfg(feature = "comdis")]
11use crate::messages::comdis::ComdisMessage;
12#[cfg(feature = "contrl")]
13use crate::messages::contrl::ContrlMessage;
14#[cfg(feature = "iftsta")]
15use crate::messages::iftsta::IftstaMessage;
16#[cfg(feature = "insrpt")]
17use crate::messages::insrpt::InsrptMessage;
18#[cfg(feature = "invoic")]
19use crate::messages::invoic::InvoicMessage;
20#[cfg(feature = "mscons")]
21use crate::messages::mscons::MsconsMessage;
22#[cfg(feature = "ordchg")]
23use crate::messages::ordchg::OrdchgMessage;
24#[cfg(feature = "orders")]
25use crate::messages::orders::OrdersMessage;
26#[cfg(feature = "ordrsp")]
27use crate::messages::ordrsp::OrdrespMessage;
28#[cfg(feature = "partin")]
29use crate::messages::partin::PartinMessage;
30#[cfg(feature = "pricat")]
31use crate::messages::pricat::PricatMessage;
32#[cfg(feature = "quotes")]
33use crate::messages::quotes::QuotesMessage;
34#[cfg(feature = "remadv")]
35use crate::messages::remadv::RemadvMessage;
36#[cfg(feature = "reqote")]
37use crate::messages::reqote::ReqoteMessage;
38#[cfg(feature = "utilmd")]
39use crate::messages::utilmd::UtilmdMessage;
40#[cfg(feature = "utilts")]
41use crate::messages::utilts::UtiltsMessage;
42
43#[derive(Debug)]
57pub enum AnyMessage {
58 #[cfg(feature = "utilmd")]
60 Utilmd(UtilmdMessage),
61
62 #[cfg(feature = "mscons")]
64 Mscons(MsconsMessage),
65
66 #[cfg(feature = "aperak")]
68 Aperak(AperakMessage),
69
70 #[cfg(feature = "contrl")]
72 Contrl(ContrlMessage),
73
74 #[cfg(feature = "invoic")]
76 Invoic(InvoicMessage),
77
78 #[cfg(feature = "remadv")]
80 Remadv(RemadvMessage),
81
82 #[cfg(feature = "orders")]
84 Orders(OrdersMessage),
85
86 #[cfg(feature = "iftsta")]
88 Iftsta(IftstaMessage),
89
90 #[cfg(feature = "insrpt")]
92 Insrpt(InsrptMessage),
93
94 #[cfg(feature = "reqote")]
96 Reqote(ReqoteMessage),
97
98 #[cfg(feature = "partin")]
100 Partin(PartinMessage),
101
102 #[cfg(feature = "ordchg")]
104 Ordchg(OrdchgMessage),
105
106 #[cfg(feature = "ordrsp")]
108 Ordrsp(OrdrespMessage),
109
110 #[cfg(feature = "quotes")]
112 Quotes(QuotesMessage),
113
114 #[cfg(feature = "comdis")]
116 Comdis(ComdisMessage),
117
118 #[cfg(feature = "pricat")]
120 Pricat(PricatMessage),
121
122 #[cfg(feature = "utilts")]
124 Utilts(UtiltsMessage),
125
126 Unknown {
147 message_type_code: Box<str>,
149 release: Release,
151 message_ref: Box<str>,
153 segments: Vec<OwnedSegment>,
155 },
156}
157
158impl AnyMessage {
159 #[must_use]
163 pub fn is_known(&self) -> bool {
164 !matches!(self, AnyMessage::Unknown { .. })
165 }
166
167 #[must_use]
173 pub fn try_message_type(&self) -> Option<MessageType> {
174 <Self as EdiEnergyMessage>::try_message_type(self)
177 }
178
179 #[cfg(feature = "utilmd")]
183 #[must_use]
184 pub fn as_utilmd(&self) -> Option<&crate::messages::utilmd::UtilmdMessage> {
185 if let AnyMessage::Utilmd(m) = self {
186 Some(m)
187 } else {
188 None
189 }
190 }
191
192 #[cfg(feature = "mscons")]
194 #[must_use]
195 pub fn as_mscons(&self) -> Option<&crate::messages::mscons::MsconsMessage> {
196 if let AnyMessage::Mscons(m) = self {
197 Some(m)
198 } else {
199 None
200 }
201 }
202
203 #[cfg(feature = "aperak")]
205 #[must_use]
206 pub fn as_aperak(&self) -> Option<&crate::messages::aperak::AperakMessage> {
207 if let AnyMessage::Aperak(m) = self {
208 Some(m)
209 } else {
210 None
211 }
212 }
213
214 #[cfg(feature = "contrl")]
216 #[must_use]
217 pub fn as_contrl(&self) -> Option<&crate::messages::contrl::ContrlMessage> {
218 if let AnyMessage::Contrl(m) = self {
219 Some(m)
220 } else {
221 None
222 }
223 }
224
225 #[cfg(feature = "invoic")]
227 #[must_use]
228 pub fn as_invoic(&self) -> Option<&crate::messages::invoic::InvoicMessage> {
229 if let AnyMessage::Invoic(m) = self {
230 Some(m)
231 } else {
232 None
233 }
234 }
235
236 #[cfg(feature = "remadv")]
238 #[must_use]
239 pub fn as_remadv(&self) -> Option<&crate::messages::remadv::RemadvMessage> {
240 if let AnyMessage::Remadv(m) = self {
241 Some(m)
242 } else {
243 None
244 }
245 }
246
247 #[cfg(feature = "orders")]
249 #[must_use]
250 pub fn as_orders(&self) -> Option<&crate::messages::orders::OrdersMessage> {
251 if let AnyMessage::Orders(m) = self {
252 Some(m)
253 } else {
254 None
255 }
256 }
257
258 #[cfg(feature = "iftsta")]
260 #[must_use]
261 pub fn as_iftsta(&self) -> Option<&crate::messages::iftsta::IftstaMessage> {
262 if let AnyMessage::Iftsta(m) = self {
263 Some(m)
264 } else {
265 None
266 }
267 }
268
269 #[cfg(feature = "insrpt")]
271 #[must_use]
272 pub fn as_insrpt(&self) -> Option<&crate::messages::insrpt::InsrptMessage> {
273 if let AnyMessage::Insrpt(m) = self {
274 Some(m)
275 } else {
276 None
277 }
278 }
279
280 #[cfg(feature = "reqote")]
282 #[must_use]
283 pub fn as_reqote(&self) -> Option<&crate::messages::reqote::ReqoteMessage> {
284 if let AnyMessage::Reqote(m) = self {
285 Some(m)
286 } else {
287 None
288 }
289 }
290
291 #[cfg(feature = "partin")]
293 #[must_use]
294 pub fn as_partin(&self) -> Option<&crate::messages::partin::PartinMessage> {
295 if let AnyMessage::Partin(m) = self {
296 Some(m)
297 } else {
298 None
299 }
300 }
301
302 #[cfg(feature = "ordchg")]
304 #[must_use]
305 pub fn as_ordchg(&self) -> Option<&crate::messages::ordchg::OrdchgMessage> {
306 if let AnyMessage::Ordchg(m) = self {
307 Some(m)
308 } else {
309 None
310 }
311 }
312
313 #[cfg(feature = "ordrsp")]
315 #[must_use]
316 pub fn as_ordrsp(&self) -> Option<&crate::messages::ordrsp::OrdrespMessage> {
317 if let AnyMessage::Ordrsp(m) = self {
318 Some(m)
319 } else {
320 None
321 }
322 }
323
324 #[cfg(feature = "quotes")]
326 #[must_use]
327 pub fn as_quotes(&self) -> Option<&crate::messages::quotes::QuotesMessage> {
328 if let AnyMessage::Quotes(m) = self {
329 Some(m)
330 } else {
331 None
332 }
333 }
334
335 #[cfg(feature = "comdis")]
337 #[must_use]
338 pub fn as_comdis(&self) -> Option<&crate::messages::comdis::ComdisMessage> {
339 if let AnyMessage::Comdis(m) = self {
340 Some(m)
341 } else {
342 None
343 }
344 }
345
346 #[cfg(feature = "pricat")]
348 #[must_use]
349 pub fn as_pricat(&self) -> Option<&crate::messages::pricat::PricatMessage> {
350 if let AnyMessage::Pricat(m) = self {
351 Some(m)
352 } else {
353 None
354 }
355 }
356
357 #[cfg(feature = "utilts")]
359 #[must_use]
360 pub fn as_utilts(&self) -> Option<&crate::messages::utilts::UtiltsMessage> {
361 if let AnyMessage::Utilts(m) = self {
362 Some(m)
363 } else {
364 None
365 }
366 }
367
368 #[cfg(any(
373 feature = "utilmd",
374 feature = "mscons",
375 feature = "aperak",
376 feature = "contrl",
377 feature = "invoic",
378 feature = "remadv",
379 feature = "orders",
380 feature = "iftsta",
381 feature = "insrpt",
382 feature = "reqote",
383 feature = "partin",
384 feature = "ordchg",
385 feature = "ordrsp",
386 feature = "quotes",
387 feature = "comdis",
388 feature = "pricat",
389 feature = "utilts",
390 ))]
391 #[must_use]
392 pub(crate) fn message_core(&self) -> Option<&crate::messages::core::MessageCore> {
393 match self {
394 #[cfg(feature = "utilmd")]
395 AnyMessage::Utilmd(m) => Some(&m.core),
396 #[cfg(feature = "mscons")]
397 AnyMessage::Mscons(m) => Some(&m.core),
398 #[cfg(feature = "aperak")]
399 AnyMessage::Aperak(m) => Some(&m.core),
400 #[cfg(feature = "contrl")]
401 AnyMessage::Contrl(m) => Some(&m.core),
402 #[cfg(feature = "invoic")]
403 AnyMessage::Invoic(m) => Some(&m.core),
404 #[cfg(feature = "remadv")]
405 AnyMessage::Remadv(m) => Some(&m.core),
406 #[cfg(feature = "orders")]
407 AnyMessage::Orders(m) => Some(&m.core),
408 #[cfg(feature = "iftsta")]
409 AnyMessage::Iftsta(m) => Some(&m.core),
410 #[cfg(feature = "insrpt")]
411 AnyMessage::Insrpt(m) => Some(&m.core),
412 #[cfg(feature = "reqote")]
413 AnyMessage::Reqote(m) => Some(&m.core),
414 #[cfg(feature = "partin")]
415 AnyMessage::Partin(m) => Some(&m.core),
416 #[cfg(feature = "ordchg")]
417 AnyMessage::Ordchg(m) => Some(&m.core),
418 #[cfg(feature = "ordrsp")]
419 AnyMessage::Ordrsp(m) => Some(&m.core),
420 #[cfg(feature = "quotes")]
421 AnyMessage::Quotes(m) => Some(&m.core),
422 #[cfg(feature = "comdis")]
423 AnyMessage::Comdis(m) => Some(&m.core),
424 #[cfg(feature = "pricat")]
425 AnyMessage::Pricat(m) => Some(&m.core),
426 #[cfg(feature = "utilts")]
427 AnyMessage::Utilts(m) => Some(&m.core),
428 AnyMessage::Unknown { .. } => None,
429 }
430 }
431}
432
433macro_rules! delegate_any {
436 ($self:expr, $inner:ident => $body:expr) => {
437 match $self {
438 #[cfg(feature = "utilmd")]
439 AnyMessage::Utilmd($inner) => $body,
440 #[cfg(feature = "mscons")]
441 AnyMessage::Mscons($inner) => $body,
442 #[cfg(feature = "aperak")]
443 AnyMessage::Aperak($inner) => $body,
444 #[cfg(feature = "contrl")]
445 AnyMessage::Contrl($inner) => $body,
446 #[cfg(feature = "invoic")]
447 AnyMessage::Invoic($inner) => $body,
448 #[cfg(feature = "remadv")]
449 AnyMessage::Remadv($inner) => $body,
450 #[cfg(feature = "orders")]
451 AnyMessage::Orders($inner) => $body,
452 #[cfg(feature = "iftsta")]
453 AnyMessage::Iftsta($inner) => $body,
454 #[cfg(feature = "insrpt")]
455 AnyMessage::Insrpt($inner) => $body,
456 #[cfg(feature = "reqote")]
457 AnyMessage::Reqote($inner) => $body,
458 #[cfg(feature = "partin")]
459 AnyMessage::Partin($inner) => $body,
460 #[cfg(feature = "ordchg")]
461 AnyMessage::Ordchg($inner) => $body,
462 #[cfg(feature = "ordrsp")]
463 AnyMessage::Ordrsp($inner) => $body,
464 #[cfg(feature = "quotes")]
465 AnyMessage::Quotes($inner) => $body,
466 #[cfg(feature = "comdis")]
467 AnyMessage::Comdis($inner) => $body,
468 #[cfg(feature = "pricat")]
469 AnyMessage::Pricat($inner) => $body,
470 #[cfg(feature = "utilts")]
471 AnyMessage::Utilts($inner) => $body,
472 AnyMessage::Unknown {
473 message_type_code,
474 release,
475 message_ref: _,
476 segments,
477 } => {
478 let _ = (message_type_code, release, segments);
479 unreachable!("Unknown variant must be handled before delegation")
480 }
481 }
482 };
483}
484
485#[allow(unreachable_patterns)]
489impl EdiEnergyMessage for AnyMessage {
490 fn try_message_type(&self) -> Option<MessageType> {
491 match self {
492 AnyMessage::Unknown { .. } => None,
493 _ => delegate_any!(self, m => m.try_message_type()),
494 }
495 }
496
497 fn detect_release(&self) -> Result<&Release, Error> {
498 match self {
499 AnyMessage::Unknown { release, .. } => Ok(release),
500 _ => delegate_any!(self, m => m.detect_release()),
501 }
502 }
503
504 fn message_ref(&self) -> &str {
505 match self {
506 AnyMessage::Unknown { message_ref, .. } => message_ref,
507 _ => delegate_any!(self, m => m.message_ref()),
508 }
509 }
510
511 fn detect_pruefidentifikator(&self) -> Result<Pruefidentifikator, Error> {
512 match self {
513 AnyMessage::Unknown { .. } => Err(Error::MissingPruefidentifikator),
514 _ => delegate_any!(self, m => m.detect_pruefidentifikator()),
515 }
516 }
517
518 fn validate(&self) -> Result<EdiEnergyReport, Error> {
519 match self {
520 AnyMessage::Unknown {
521 message_type_code, ..
522 } => {
523 use edifact_rs::{ValidationIssue, ValidationReport, ValidationSeverity};
524 let mut inner = ValidationReport::default();
525 inner.add_error(
526 ValidationIssue::new(
527 ValidationSeverity::Error,
528 format!(
529 "message type {message_type_code:?} is not validated in this build"
530 ),
531 )
532 .with_rule_id("UNKNOWN-MSG-TYPE"),
533 );
534 Ok(EdiEnergyReport::new(inner))
535 }
536 _ => delegate_any!(self, m => m.validate()),
537 }
538 }
539
540 #[allow(unused_variables)]
541 fn validate_against(&self, release: &Release) -> Result<EdiEnergyReport, Error> {
542 match self {
543 AnyMessage::Unknown {
544 message_type_code, ..
545 } => {
546 use edifact_rs::{ValidationIssue, ValidationReport, ValidationSeverity};
547 let mut inner = ValidationReport::default();
548 inner.add_error(
549 ValidationIssue::new(
550 ValidationSeverity::Error,
551 format!(
552 "message type {message_type_code:?} is not validated in this build"
553 ),
554 )
555 .with_rule_id("UNKNOWN-MSG-TYPE"),
556 );
557 Ok(EdiEnergyReport::new(inner))
558 }
559 _ => delegate_any!(self, m => m.validate_against(release)),
560 }
561 }
562
563 fn serialize(&self) -> Result<Vec<u8>, Error> {
564 match self {
565 AnyMessage::Unknown { segments, .. } => {
566 edifact_rs::segments_to_bytes_owned(segments).map_err(Error::Parse)
567 }
568 _ => delegate_any!(self, m => m.serialize()),
569 }
570 }
571
572 fn segments(&self) -> &[OwnedSegment] {
573 match self {
574 AnyMessage::Unknown { segments, .. } => segments,
575 _ => delegate_any!(self, m => m.segments()),
576 }
577 }
578
579 fn validate_with_pack(&self, extra: CustomRulePack) -> Result<EdiEnergyReport, Error> {
580 match self {
581 AnyMessage::Unknown { .. } => {
582 let _ = extra;
583 Err(Error::MissingRelease)
584 }
585 _ => delegate_any!(self, m => m.validate_with_pack(extra)),
586 }
587 }
588
589 #[allow(unused_variables)]
590 fn validate_on_date(&self, reference_date: time::Date) -> Result<EdiEnergyReport, Error> {
591 match self {
592 AnyMessage::Unknown {
593 message_type_code, ..
594 } => {
595 use edifact_rs::{ValidationIssue, ValidationReport, ValidationSeverity};
596 let mut inner = ValidationReport::default();
597 inner.add_error(
598 ValidationIssue::new(
599 ValidationSeverity::Error,
600 format!(
601 "message type {message_type_code:?} is not validated in this build"
602 ),
603 )
604 .with_rule_id("UNKNOWN-MSG-TYPE"),
605 );
606 Ok(EdiEnergyReport::new(inner))
607 }
608 _ => delegate_any!(self, m => m.validate_on_date(reference_date)),
609 }
610 }
611}