libp2p_gossipsub/
topic.rs1use std::fmt;
22
23use base64::prelude::*;
24use quick_protobuf::Writer;
25use sha2::{Digest, Sha256};
26
27use crate::rpc_proto::proto;
28
29pub trait Hasher {
31 fn hash(topic_string: String) -> TopicHash;
33}
34
35#[derive(Debug, Clone)]
37pub struct IdentityHash {}
38impl Hasher for IdentityHash {
39 fn hash(topic_string: String) -> TopicHash {
41 TopicHash { hash: topic_string }
42 }
43}
44
45#[derive(Debug, Clone)]
46pub struct Sha256Hash {}
47impl Hasher for Sha256Hash {
48 fn hash(topic_string: String) -> TopicHash {
51 use quick_protobuf::MessageWrite;
52
53 let topic_descriptor = proto::TopicDescriptor {
54 name: Some(topic_string),
55 auth: None,
56 enc: None,
57 };
58 let mut bytes = Vec::with_capacity(topic_descriptor.get_size());
59 let mut writer = Writer::new(&mut bytes);
60 topic_descriptor
61 .write_message(&mut writer)
62 .expect("Encoding to succeed");
63 let hash = BASE64_STANDARD.encode(Sha256::digest(&bytes));
64 TopicHash { hash }
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
69#[cfg_attr(
70 feature = "metrics",
71 derive(prometheus_client::encoding::EncodeLabelSet)
72)]
73pub struct TopicHash {
74 hash: String,
76}
77
78impl TopicHash {
79 pub fn from_raw(hash: impl Into<String>) -> TopicHash {
80 TopicHash { hash: hash.into() }
81 }
82
83 pub fn into_string(self) -> String {
84 self.hash
85 }
86
87 pub fn as_str(&self) -> &str {
88 &self.hash
89 }
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
94pub struct Topic<H: Hasher> {
95 topic: String,
96 phantom_data: std::marker::PhantomData<H>,
97}
98
99impl<H: Hasher> From<Topic<H>> for TopicHash {
100 fn from(topic: Topic<H>) -> TopicHash {
101 topic.hash()
102 }
103}
104
105impl<H: Hasher> Topic<H> {
106 pub fn new(topic: impl Into<String>) -> Self {
107 Topic {
108 topic: topic.into(),
109 phantom_data: std::marker::PhantomData,
110 }
111 }
112
113 pub fn hash(&self) -> TopicHash {
114 H::hash(self.topic.clone())
115 }
116}
117
118impl<H: Hasher> fmt::Display for Topic<H> {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 write!(f, "{}", self.topic)
121 }
122}
123
124impl fmt::Display for TopicHash {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "{}", self.hash)
127 }
128}