elfo_core/message/
protocol.rs1use std::ops::Deref;
2
3#[doc(hidden)]
7pub struct ProtocolExtractor;
8
9#[doc(hidden)]
11pub trait ProtocolHolder {
12 const PROTOCOL: Option<&'static str>;
13}
14
15#[doc(hidden)]
17pub struct DefaultProtocolHolder;
18
19impl ProtocolHolder for DefaultProtocolHolder {
20 const PROTOCOL: Option<&'static str> = None;
22}
23
24impl Deref for ProtocolExtractor {
25 type Target = DefaultProtocolHolder;
26
27 fn deref(&self) -> &Self::Target {
28 &DefaultProtocolHolder
29 }
30}
31
32impl DefaultProtocolHolder {
33 pub fn holder(&self) -> Self {
34 Self
35 }
36}
37
38#[macro_export]
43macro_rules! set_protocol {
44 ($protocol:literal) => {
45 #[doc(hidden)]
46 struct _ElfoProtocolHolder;
47 impl $crate::_priv::ProtocolHolder for _ElfoProtocolHolder {
48 const PROTOCOL: Option<&'static str> = Some($protocol);
49 }
50
51 #[doc(hidden)]
52 trait _ElfoProtocolOverride {
53 fn holder(&self) -> _ElfoProtocolHolder {
54 _ElfoProtocolHolder
55 }
56 }
57 impl _ElfoProtocolOverride for $crate::_priv::ProtocolExtractor {}
58 };
59}
60
61#[doc(hidden)]
62#[macro_export]
63macro_rules! get_protocol {
64 () => {{
65 use $crate::_priv::{ProtocolExtractor, ProtocolHolder};
66
67 const fn extract_protocol_name<H: ProtocolHolder>(_: &impl FnOnce() -> H) -> &'static str {
68 if let Some(proto_override) = H::PROTOCOL {
70 return proto_override;
71 }
72
73 if let Some(pkg_name) = option_env!("CARGO_PKG_NAME") {
75 return pkg_name;
76 }
77
78 panic!(
79 "if the crate is built without cargo, \
80 the protocol must be set explicitly by calling `elfo::set_protocol!(..)`"
81 );
82 }
83
84 extract_protocol_name(&|| ProtocolExtractor.holder())
85 }};
86}