pub mod mako {
pub const PROCESS_INITIATED: &str = "de.mako.process.initiated";
pub const PROCESS_COMPLETED: &str = "de.mako.process.completed";
pub const PROCESS_FAILED: &str = "de.mako.process.failed";
pub const APERAK_ACCEPTED: &str = "de.mako.aperak.accepted";
pub const APERAK_REJECTED: &str = "de.mako.aperak.rejected";
pub const APERAK_TIMEOUT: &str = "de.mako.aperak.timeout";
pub const CONTRL_RECEIVED: &str = "de.mako.contrl.received";
pub const MALO_IDENTIFIED: &str = "de.mako.malo.identified";
pub const EDIFACT_OUTBOUND: &str = "de.mako.edifact.outbound";
pub const EDIFACT_INBOUND: &str = "de.mako.edifact.inbound";
pub const NETZZUGANG_UEBERMITTLUNGSBEDARF: &str = "de.mako.netzzugang.uebermittlungsbedarf";
}
pub mod markt {
pub const MALO_UPDATED: &str = "de.markt.malo.updated";
pub const MALO_STAMMDATEN_GEAENDERT: &str = "de.markt.malo.stammdaten-geaendert";
pub const STAMMDATEN_GEAENDERT: &str = "de.markt.stammdaten.geaendert";
pub const MELO_UPDATED: &str = "de.markt.melo.updated";
pub const PARTNER_UPDATED: &str = "de.markt.partner.updated";
pub const NB_CONTRACT_UPDATED: &str = "de.markt.nb-contract.updated";
pub const MSB_RAHMENVERTRAG_GAS_UPDATED: &str = "de.markt.msb-rahmenvertrag-gas.updated";
pub const GERAET_KONFIGURATION_UPDATED: &str = "de.markt.geraet.konfiguration.updated";
pub const SR_KONFIGURATIONSPRODUKT_UPDATED: &str = "de.markt.sr.konfigurationsprodukt.updated";
pub const NETZZUGANG_ANTRAG_UPDATED: &str = "de.markt.netzzugang.antrag.updated";
pub const EINWILLIGUNG_ERTEILT: &str = "de.markt.einwilligung.erteilt";
pub const EINWILLIGUNG_WIDERRUFEN: &str = "de.markt.einwilligung.widerrufen";
pub const VERSORGUNG_CHANGED: &str = "de.markt.versorgung.changed";
pub const VERSORGUNG_BELIEFERT: &str = "de.markt.versorgung.beliefert";
pub const VERSORGUNG_GAP_DETECTED: &str = "de.markt.versorgung.gap-detected";
pub const VERSORGUNG_EOG_BEGONNEN: &str = "de.markt.versorgung.eog-begonnen";
pub const VERSORGUNG_ERSATZ_AUSLAUFEND: &str = "de.markt.versorgung.ersatz-auslaufend";
pub const PRICAT_PUBLISHED: &str = "de.markt.pricat.published";
pub const MMMA_IMPORT_SUCCESS: &str = "de.markt.mmma.import.success";
pub const MMMA_IMPORT_FAILED: &str = "de.markt.mmma.import.failed";
pub const SUBSCRIPTION_TEST: &str = "de.markt.subscription.test";
}
pub mod billing {
pub const RECHNUNG_ERSTELLT: &str = "de.billing.rechnung.erstellt";
pub const ABRECHNUNGSINFORMATION_MONATLICH: &str =
"de.billing.abrechnungsinformation.monatlich";
pub const XRECHNUNG_B2G_READY: &str = "de.billing.xrechnung.b2g.ready";
}
pub mod invoic {
pub const RECEIPT_DISPUTED: &str = "de.invoic.receipt.disputed";
pub const RECEIPT_DISPATCHED: &str = "de.invoic.receipt.dispatched";
pub const RECEIPT_SETTLED: &str = "de.invoic.receipt.settled";
pub const PAYMENT_OVERDUE: &str = "de.invoic.payment.overdue";
}
pub mod eeg {
pub const VERGUETUNG_BERECHNET: &str = "de.eeg.verguetung.berechnet";
pub const MARKTPRAEMIE_BERECHNET: &str = "de.eeg.marktpraemie.berechnet";
pub const SETTLEMENT_BERECHNET: &str = "de.eeg.settlement.berechnet";
pub const SETTLEMENT_BATCH_DUE: &str = "de.eeg.settlement.batch-due";
pub const ANLAGE_FOERDERUNG_AUSLAUFEND: &str = "de.eeg.anlage.foerderung-auslaufend";
pub const ANLAGE_MASTR_REGISTRIERT: &str = "de.eeg.anlage.mastr-registriert";
pub const VERAEUSSERUNGSFORM_GEWECHSELT: &str = "de.eeg.veraeusserungsform.gewechselt";
}
pub mod accounting {
pub const MAHNUNG_ISSUED: &str = "de.accounting.mahnung.issued";
pub const ABSCHLAG_POSTED: &str = "de.accounting.abschlag.posted";
pub const PAYMENT_DUE: &str = "de.accounting.payment.due";
pub const PAYMENT_IMPORTED: &str = "de.accounting.payment.imported";
pub const ERSTATTUNG_FAELLIG: &str = "de.accounting.erstattung.faellig";
pub const INTEREST_CHARGED: &str = "de.accounting.interest.charged";
pub const EEG_PAYOUT_REJECTED: &str = "de.accounting.eeg.payout.rejected";
pub const SPERRANDROHUNG: &str = "de.accounting.sperrandrohung";
pub const SPERRANKUENDIGUNG: &str = "de.accounting.sperrankuendigung";
pub const SPERRAUFTRAG: &str = "de.accounting.sperrauftrag";
pub const BANKRUECKLAST: &str = "de.accounting.bankruecklast";
}
pub mod netzbilanz {
pub const INVOIC_DRAFTED: &str = "de.netzbilanz.invoic.drafted";
pub const INVOIC_DISPATCHED: &str = "de.netzbilanz.invoic.dispatched";
pub const INVOIC_DISPATCH_OVERDUE: &str = "de.netzbilanz.invoic.dispatch-overdue";
pub const INVOIC_PAID: &str = "de.netzbilanz.invoic.paid";
pub const INVOIC_DISPUTED: &str = "de.netzbilanz.invoic.disputed";
pub const KOSTENBLATT_COMPUTED: &str = "de.netzbilanz.kostenblatt.computed";
pub const KOSTENBLATT_DEADLINE_APPROACHING: &str =
"de.netzbilanz.kostenblatt.deadline-approaching";
}
pub mod messwert {
pub const READING_QUALITY_WARNING: &str = "de.messwert.reading.quality.warning";
pub const READING_DIRECT_STORED: &str = "de.messwert.reading.direct.stored";
pub const READING_ORDER_FAILED: &str = "de.messwert.reading.order.failed";
pub const READING_CONFIRMATION_OVERDUE: &str = "de.messwert.reading.confirmation.overdue";
pub const CLS_COMPLIANCE_ISSUE: &str = "de.messwert.cls.compliance-issue";
pub const SMGW_CERT_EXPIRY_WARNING: &str = "de.messwert.smgw.cert.expiry-warning";
}
pub mod tarif {
pub const PRODUCT_UPDATED: &str = "de.tarif.product.updated";
pub const ANGEBOT_ANGENOMMEN: &str = "de.tarif.angebot.angenommen";
pub const ANGEBOT_ABGELAUFEN: &str = "de.tarif.angebot.abgelaufen";
pub const EPEX_MISSING: &str = "de.tarif.epex.missing";
}
pub mod vertrag {
pub const AKTIV: &str = "de.vertrag.aktiv";
pub const GEKUENDIGT: &str = "de.vertrag.gekuendigt";
pub const KUENDIGUNG: &str = "de.vertrag.kuendigung";
pub const KUENDIGUNG_WIDERRUFEN: &str = "de.vertrag.kuendigung-widerrufen";
pub const TARIFWECHSEL: &str = "de.vertrag.tarifwechsel";
pub const TARIFWECHSEL_GEPLANT: &str = "de.vertrag.tarifwechsel-geplant";
pub const PREISGARANTIE_UPDATED: &str = "de.vertrag.preisgarantie-updated";
pub const PREISAENDERUNG_ANKUENDIGUNG: &str = "de.vertrag.preisaenderung.ankuendigung";
pub const AUTOERNEUERUNG_ANKUENDIGUNG: &str = "de.vertrag.autoerneuerung.ankuendigung";
pub const ABLAUF_ANKUENDIGUNG: &str = "de.vertrag.ablauf.ankuendigung";
}
pub mod vpp {
pub const DISPATCH_CONFIRMED: &str = "de.vpp.dispatch.confirmed";
pub const SETTLEMENT_BERECHNET: &str = "de.vpp.settlement.berechnet";
}
pub mod agent {
pub const DECISION_MADE: &str = "de.agent.decision.made";
pub const SESSION_DLQ_EXHAUSTED: &str = "de.agent.session.dlq.exhausted";
}
pub mod gabi {
pub const MEASUREMENT_RECEIVED: &str = "de.gabi.measurement.received";
pub const ALLOCATION_COMPLETED: &str = "de.gabi.allocation.completed";
pub const NOMINATION_CREATED: &str = "de.gabi.nomination.created";
pub const NOMINATION_CONFIRMED: &str = "de.gabi.nomination.confirmed";
pub const IMBALANCE_CALCULATED: &str = "de.gabi.imbalance.calculated";
pub const CORRECTION_CREATED: &str = "de.gabi.correction.created";
pub const INVOIC_MMM_RECEIVED: &str = "de.gabi.invoic.mmm.received";
pub const INVOIC_KAPAZITAET_RECEIVED: &str = "de.gabi.invoic.kapazitaet.received";
pub const ALOCAT_MISSING: &str = "de.gabi.alocat.missing";
pub const IMBNOT_RECEIVED: &str = "de.gabi.imbnot.received";
pub const GAS_QUALITY_VIOLATION: &str = "de.gabi.quality.violation";
pub const FINAL_ALOCAT_DEADLINE: &str = "de.gabi.alocat.final.deadline";
}
pub mod obs {
pub const STP_PARITY_ALERT: &str = "de.obs.stp.parity.alert";
pub const DEADLINE_APPROACHING: &str = "de.obs.deadline.approaching";
}
pub mod sperr {}
#[must_use]
pub fn all() -> &'static [&'static str] {
&[
mako::PROCESS_INITIATED,
mako::PROCESS_COMPLETED,
mako::PROCESS_FAILED,
mako::APERAK_ACCEPTED,
mako::APERAK_REJECTED,
mako::APERAK_TIMEOUT,
mako::CONTRL_RECEIVED,
mako::MALO_IDENTIFIED,
mako::EDIFACT_OUTBOUND,
mako::EDIFACT_INBOUND,
mako::NETZZUGANG_UEBERMITTLUNGSBEDARF,
markt::MALO_UPDATED,
markt::MALO_STAMMDATEN_GEAENDERT,
markt::MELO_UPDATED,
markt::PARTNER_UPDATED,
markt::NB_CONTRACT_UPDATED,
markt::MSB_RAHMENVERTRAG_GAS_UPDATED,
markt::GERAET_KONFIGURATION_UPDATED,
markt::SR_KONFIGURATIONSPRODUKT_UPDATED,
markt::NETZZUGANG_ANTRAG_UPDATED,
markt::EINWILLIGUNG_ERTEILT,
markt::EINWILLIGUNG_WIDERRUFEN,
markt::VERSORGUNG_CHANGED,
markt::VERSORGUNG_BELIEFERT,
markt::VERSORGUNG_GAP_DETECTED,
markt::VERSORGUNG_EOG_BEGONNEN,
markt::VERSORGUNG_ERSATZ_AUSLAUFEND,
markt::PRICAT_PUBLISHED,
markt::MMMA_IMPORT_SUCCESS,
markt::MMMA_IMPORT_FAILED,
markt::SUBSCRIPTION_TEST,
billing::RECHNUNG_ERSTELLT,
billing::ABRECHNUNGSINFORMATION_MONATLICH,
billing::XRECHNUNG_B2G_READY,
invoic::RECEIPT_DISPUTED,
invoic::RECEIPT_DISPATCHED,
invoic::RECEIPT_SETTLED,
invoic::PAYMENT_OVERDUE,
eeg::VERGUETUNG_BERECHNET,
eeg::MARKTPRAEMIE_BERECHNET,
eeg::SETTLEMENT_BERECHNET,
eeg::SETTLEMENT_BATCH_DUE,
eeg::ANLAGE_FOERDERUNG_AUSLAUFEND,
eeg::ANLAGE_MASTR_REGISTRIERT,
eeg::VERAEUSSERUNGSFORM_GEWECHSELT,
accounting::MAHNUNG_ISSUED,
accounting::ABSCHLAG_POSTED,
accounting::PAYMENT_DUE,
accounting::PAYMENT_IMPORTED,
accounting::ERSTATTUNG_FAELLIG,
accounting::INTEREST_CHARGED,
accounting::EEG_PAYOUT_REJECTED,
accounting::SPERRANDROHUNG,
accounting::SPERRANKUENDIGUNG,
accounting::SPERRAUFTRAG,
accounting::BANKRUECKLAST,
netzbilanz::INVOIC_DRAFTED,
netzbilanz::INVOIC_DISPATCHED,
netzbilanz::INVOIC_DISPATCH_OVERDUE,
netzbilanz::INVOIC_PAID,
netzbilanz::INVOIC_DISPUTED,
netzbilanz::KOSTENBLATT_COMPUTED,
netzbilanz::KOSTENBLATT_DEADLINE_APPROACHING,
messwert::READING_QUALITY_WARNING,
messwert::READING_DIRECT_STORED,
messwert::READING_ORDER_FAILED,
messwert::READING_CONFIRMATION_OVERDUE,
messwert::CLS_COMPLIANCE_ISSUE,
messwert::SMGW_CERT_EXPIRY_WARNING,
tarif::PRODUCT_UPDATED,
tarif::ANGEBOT_ANGENOMMEN,
tarif::ANGEBOT_ABGELAUFEN,
tarif::EPEX_MISSING,
vertrag::AKTIV,
vertrag::GEKUENDIGT,
vertrag::KUENDIGUNG,
vertrag::KUENDIGUNG_WIDERRUFEN,
vertrag::TARIFWECHSEL,
vertrag::TARIFWECHSEL_GEPLANT,
vertrag::PREISGARANTIE_UPDATED,
vertrag::PREISAENDERUNG_ANKUENDIGUNG,
vertrag::AUTOERNEUERUNG_ANKUENDIGUNG,
vertrag::ABLAUF_ANKUENDIGUNG,
vpp::DISPATCH_CONFIRMED,
vpp::SETTLEMENT_BERECHNET,
agent::DECISION_MADE,
agent::SESSION_DLQ_EXHAUSTED,
gabi::MEASUREMENT_RECEIVED,
gabi::ALLOCATION_COMPLETED,
gabi::NOMINATION_CREATED,
gabi::NOMINATION_CONFIRMED,
gabi::IMBALANCE_CALCULATED,
gabi::CORRECTION_CREATED,
gabi::INVOIC_MMM_RECEIVED,
gabi::INVOIC_KAPAZITAET_RECEIVED,
gabi::ALOCAT_MISSING,
gabi::IMBNOT_RECEIVED,
gabi::GAS_QUALITY_VIOLATION,
gabi::FINAL_ALOCAT_DEADLINE,
obs::STP_PARITY_ALERT,
obs::DEADLINE_APPROACHING,
]
}
#[must_use]
pub fn matches(pattern: &str, event_type: &str) -> bool {
if pattern == "*" {
return true;
}
let p: Vec<char> = pattern.chars().collect();
let v: Vec<char> = event_type.chars().collect();
let mut pi = 0usize;
let mut vi = 0usize;
let mut star_pi: Option<usize> = None;
let mut star_vi = 0usize;
while vi < v.len() {
if pi < p.len() && (p[pi] == '?' || p[pi] == v[vi]) {
pi += 1;
vi += 1;
} else if pi < p.len() && p[pi] == '*' {
star_pi = Some(pi);
star_vi = vi;
pi += 1;
} else if let Some(sp) = star_pi {
pi = sp + 1;
star_vi += 1;
vi = star_vi;
} else {
return false;
}
}
while pi < p.len() && p[pi] == '*' {
pi += 1;
}
pi == p.len()
}
#[cfg(test)]
mod matcher_tests {
use super::matches;
#[test]
fn exact_and_bare_star() {
assert!(matches(
super::mako::PROCESS_INITIATED,
super::mako::PROCESS_INITIATED
));
assert!(!matches(
super::mako::PROCESS_INITIATED,
super::mako::PROCESS_COMPLETED
));
assert!(matches("*", "de.anything.at.all"));
}
#[test]
fn trailing_star_is_prefix_match() {
assert!(matches("de.mako.*", "de.mako.process.initiated"));
assert!(matches("de.markt.*", "de.markt.malo.updated"));
assert!(!matches("de.mako.*", "de.markt.malo.updated"));
assert!(matches("de.mako.process.*", "de.mako.process.failed"));
}
#[test]
fn mid_glob_and_question_mark() {
assert!(matches(
"de.*.rechnung.erstellt",
"de.billing.rechnung.erstellt"
));
assert!(matches(
"de.e?g.verguetung.berechnet",
"de.eeg.verguetung.berechnet"
));
assert!(!matches(
"de.e?g.verguetung.berechnet",
"de.eeeg.verguetung.berechnet"
));
}
#[test]
fn empty_pattern_matches_only_empty() {
assert!(matches("", ""));
assert!(!matches("", "de.x"));
}
}
#[cfg(test)]
mod tests {
use super::all;
#[test]
fn every_type_starts_with_de_prefix() {
for ty in all() {
assert!(ty.starts_with("de."), "{ty} must start with `de.`");
}
}
#[test]
fn segments_use_hyphen_not_underscore() {
for ty in all() {
assert!(
!ty.contains('_'),
"{ty} must join multi-word segments with `-`, not `_`"
);
for segment in ty.split('.') {
assert!(
!segment.is_empty(),
"{ty} must not contain an empty segment"
);
assert!(
!segment.starts_with('-') && !segment.ends_with('-'),
"{ty}: segment {segment:?} must not start or end with `-`"
);
assert!(
segment
.bytes()
.all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'-'),
"{ty}: segment {segment:?} must match [a-z0-9-]+"
);
}
}
}
#[test]
fn no_two_types_normalise_to_the_same_name() {
let mut seen: std::collections::HashMap<String, &str> = std::collections::HashMap::new();
for ty in all() {
let key = ty.replace(['-', '_'], "").to_lowercase();
if let Some(prev) = seen.insert(key, ty) {
assert_eq!(prev, *ty, "{prev} and {ty} collide after normalisation");
}
}
}
#[test]
fn every_type_is_lowercase() {
for ty in all() {
assert_eq!(
*ty,
ty.to_lowercase(),
"{ty} must be entirely lowercase (CloudEvents type convention)"
);
}
}
#[test]
fn every_type_has_valid_segments() {
for ty in all() {
assert!(
!ty.contains(' ') && !ty.contains('*'),
"{ty} must be a concrete type — no whitespace, no globs"
);
for segment in ty.split('.') {
assert!(!segment.is_empty(), "{ty} has an empty `.` segment");
assert!(
segment
.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || "-_".contains(c)),
"{ty}: segment `{segment}` has characters outside [a-z0-9_-]"
);
}
}
}
#[test]
fn no_duplicates() {
let types = all();
let mut seen = std::collections::BTreeSet::new();
for ty in types {
assert!(seen.insert(*ty), "duplicate catalog entry: {ty}");
}
}
#[test]
fn legacy_prefixes_are_gone() {
for ty in all() {
assert!(
!ty.starts_with("de.edmd.") && !ty.starts_with("de.tarifbd."),
"{ty} uses a retired service-name prefix (use de.messwert / de.tarif)"
);
assert_ne!(
*ty, "de.angebot.angenommen",
"moved to de.tarif.angebot.angenommen"
);
}
}
}