1use std::{
22 borrow::Borrow,
23 fmt,
24 hash::{Hash, Hasher},
25 ops::Deref,
26 sync::Arc,
27};
28
29pub use libp2p::{multiaddr, Multiaddr, PeerId};
30
31#[derive(Debug, Clone)]
33pub enum ProtocolName {
34 Static(&'static str),
36 OnHeap(Arc<str>),
38}
39
40impl From<&'static str> for ProtocolName {
41 fn from(name: &'static str) -> Self {
42 Self::Static(name)
43 }
44}
45
46impl From<Arc<str>> for ProtocolName {
47 fn from(name: Arc<str>) -> Self {
48 Self::OnHeap(name)
49 }
50}
51
52impl From<String> for ProtocolName {
53 fn from(name: String) -> Self {
54 Self::OnHeap(Arc::from(name))
55 }
56}
57
58impl Deref for ProtocolName {
59 type Target = str;
60
61 fn deref(&self) -> &str {
62 match self {
63 Self::Static(name) => name,
64 Self::OnHeap(name) => &name,
65 }
66 }
67}
68
69impl Borrow<str> for ProtocolName {
70 fn borrow(&self) -> &str {
71 self
72 }
73}
74
75impl PartialEq for ProtocolName {
76 fn eq(&self, other: &Self) -> bool {
77 (self as &str) == (other as &str)
78 }
79}
80
81impl Eq for ProtocolName {}
82
83impl Hash for ProtocolName {
84 fn hash<H: Hasher>(&self, state: &mut H) {
85 (self as &str).hash(state)
86 }
87}
88
89impl fmt::Display for ProtocolName {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 f.write_str(self)
92 }
93}
94
95impl AsRef<str> for ProtocolName {
96 fn as_ref(&self) -> &str {
97 self as &str
98 }
99}
100
101impl From<ProtocolName> for litep2p::ProtocolName {
102 fn from(protocol: ProtocolName) -> Self {
103 match protocol {
104 ProtocolName::Static(inner) => litep2p::ProtocolName::from(inner),
105 ProtocolName::OnHeap(inner) => litep2p::ProtocolName::from(inner),
106 }
107 }
108}
109
110impl From<litep2p::ProtocolName> for ProtocolName {
111 fn from(protocol: litep2p::ProtocolName) -> Self {
112 match protocol {
113 litep2p::ProtocolName::Static(protocol) => ProtocolName::from(protocol),
114 litep2p::ProtocolName::Allocated(protocol) => ProtocolName::from(protocol),
115 }
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::ProtocolName;
122 use std::{
123 borrow::Borrow,
124 collections::hash_map::DefaultHasher,
125 hash::{Hash, Hasher},
126 };
127
128 #[test]
129 fn protocol_name_keys_are_equivalent_to_str_keys() {
130 const PROTOCOL: &'static str = "/some/protocol/1";
131 let static_protocol_name = ProtocolName::from(PROTOCOL);
132 let on_heap_protocol_name = ProtocolName::from(String::from(PROTOCOL));
133
134 assert_eq!(<ProtocolName as Borrow<str>>::borrow(&static_protocol_name), PROTOCOL);
135 assert_eq!(<ProtocolName as Borrow<str>>::borrow(&on_heap_protocol_name), PROTOCOL);
136 assert_eq!(static_protocol_name, on_heap_protocol_name);
137
138 assert_eq!(hash(static_protocol_name), hash(PROTOCOL));
139 assert_eq!(hash(on_heap_protocol_name), hash(PROTOCOL));
140 }
141
142 #[test]
143 fn different_protocol_names_do_not_compare_equal() {
144 const PROTOCOL1: &'static str = "/some/protocol/1";
145 let static_protocol_name1 = ProtocolName::from(PROTOCOL1);
146 let on_heap_protocol_name1 = ProtocolName::from(String::from(PROTOCOL1));
147
148 const PROTOCOL2: &'static str = "/some/protocol/2";
149 let static_protocol_name2 = ProtocolName::from(PROTOCOL2);
150 let on_heap_protocol_name2 = ProtocolName::from(String::from(PROTOCOL2));
151
152 assert_ne!(<ProtocolName as Borrow<str>>::borrow(&static_protocol_name1), PROTOCOL2);
153 assert_ne!(<ProtocolName as Borrow<str>>::borrow(&on_heap_protocol_name1), PROTOCOL2);
154 assert_ne!(static_protocol_name1, static_protocol_name2);
155 assert_ne!(static_protocol_name1, on_heap_protocol_name2);
156 assert_ne!(on_heap_protocol_name1, on_heap_protocol_name2);
157 }
158
159 fn hash<T: Hash>(x: T) -> u64 {
160 let mut hasher = DefaultHasher::new();
161 x.hash(&mut hasher);
162 hasher.finish()
163 }
164}