use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum MessageType {
Utilmd,
Mscons,
Aperak,
Contrl,
Invoic,
Remadv,
Orders,
Iftsta,
Insrpt,
Reqote,
Partin,
Ordchg,
Ordrsp,
Quotes,
Comdis,
Pricat,
Utilts,
}
macro_rules! message_types {
($(($variant:ident, $code:literal, $feature:literal)),* $(,)?) => {
impl MessageType {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
$(Self::$variant => $code,)*
}
}
#[must_use]
pub fn from_unh_code(code: &str) -> Option<Self> {
match code {
$($code => Some(Self::$variant),)*
_ => None,
}
}
#[must_use]
pub fn feature_name(self) -> &'static str {
match self {
$(Self::$variant => $feature,)*
}
}
#[must_use]
pub fn is_feature_enabled(self) -> bool {
match self {
$(Self::$variant => cfg!(feature = $feature),)*
}
}
pub const ALL: &'static [Self] = &[$(Self::$variant),*];
}
};
}
message_types![
(Utilmd, "UTILMD", "utilmd"),
(Mscons, "MSCONS", "mscons"),
(Aperak, "APERAK", "aperak"),
(Contrl, "CONTRL", "contrl"),
(Invoic, "INVOIC", "invoic"),
(Remadv, "REMADV", "remadv"),
(Orders, "ORDERS", "orders"),
(Iftsta, "IFTSTA", "iftsta"),
(Insrpt, "INSRPT", "insrpt"),
(Reqote, "REQOTE", "reqote"),
(Partin, "PARTIN", "partin"),
(Ordchg, "ORDCHG", "ordchg"),
(Ordrsp, "ORDRSP", "ordrsp"),
(Quotes, "QUOTES", "quotes"),
(Comdis, "COMDIS", "comdis"),
(Pricat, "PRICAT", "pricat"),
(Utilts, "UTILTS", "utilts"),
];
impl fmt::Display for MessageType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::MessageType;
#[test]
fn the_table_is_a_bijection() {
let mut codes: Vec<&str> = Vec::new();
for &mt in MessageType::ALL {
assert_eq!(MessageType::from_unh_code(mt.as_str()), Some(mt));
assert_eq!(mt.feature_name(), mt.as_str().to_lowercase());
codes.push(mt.as_str());
}
let total = codes.len();
codes.sort_unstable();
codes.dedup();
assert_eq!(codes.len(), total, "two message types share a wire code");
assert_eq!(MessageType::from_unh_code("NOMINT"), None);
}
}