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
29/// The protocol name transmitted on the wire.
30#[derive(Debug, Clone)]
31pub enum ProtocolName {
32	/// The protocol name as a static string.
33	Static(&'static str),
34	/// The protocol name as a dynamically allocated string.
35	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}