qubit_event_bus/core/
topic.rs1use std::any::{
13 TypeId,
14 type_name,
15};
16use std::fmt::{
17 self,
18 Display,
19 Formatter,
20};
21use std::hash::{
22 Hash,
23 Hasher,
24};
25use std::marker::PhantomData;
26
27use crate::{
28 EventBusError,
29 EventBusResult,
30 TopicKey,
31};
32
33#[derive(Debug)]
38pub struct Topic<T: 'static> {
39 name: String,
40 payload_type_id: TypeId,
41 payload_type_name: &'static str,
42 marker: PhantomData<fn() -> T>,
43}
44
45impl<T: 'static> Topic<T> {
46 pub fn try_new(name: impl Into<String>) -> EventBusResult<Self> {
57 let name = name.into();
58 if name.trim().is_empty() {
59 return Err(EventBusError::invalid_argument(
60 "name",
61 "topic name must not be blank",
62 ));
63 }
64 Ok(Self {
65 name,
66 payload_type_id: TypeId::of::<T>(),
67 payload_type_name: type_name::<T>(),
68 marker: PhantomData,
69 })
70 }
71
72 pub fn name(&self) -> &str {
77 &self.name
78 }
79
80 pub fn payload_type_id(&self) -> TypeId {
85 self.payload_type_id
86 }
87
88 pub fn payload_type_name(&self) -> &'static str {
93 self.payload_type_name
94 }
95
96 pub fn key(&self) -> TopicKey {
101 TopicKey::new(self.name.clone(), self.payload_type_id)
102 }
103}
104
105impl<T: 'static> Clone for Topic<T> {
106 fn clone(&self) -> Self {
108 Self {
109 name: self.name.clone(),
110 payload_type_id: self.payload_type_id,
111 payload_type_name: self.payload_type_name,
112 marker: PhantomData,
113 }
114 }
115}
116
117impl<T: 'static> PartialEq for Topic<T> {
118 fn eq(&self, other: &Self) -> bool {
120 self.name == other.name && self.payload_type_id == other.payload_type_id
121 }
122}
123
124impl<T: 'static> Eq for Topic<T> {}
125
126impl<T: 'static> Hash for Topic<T> {
127 fn hash<H: Hasher>(&self, state: &mut H) {
129 self.name.hash(state);
130 self.payload_type_id.hash(state);
131 }
132}
133
134impl<T: 'static> Display for Topic<T> {
135 fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
137 write!(formatter, "{}.{}", self.payload_type_name, self.name)
138 }
139}