sc_network/
types.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! `sc-network` type definitions
20
21use 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/// The protocol name transmitted on the wire.
32#[derive(Debug, Clone)]
33pub enum ProtocolName {
34	/// The protocol name as a static string.
35	Static(&'static str),
36	/// The protocol name as a dynamically allocated string.
37	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}