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