autoagents_core/actor/
topic.rs1use crate::actor::messaging::ActorMessage;
2use std::any::TypeId;
3use std::fmt::Debug;
4use std::marker::PhantomData;
5use uuid::Uuid;
6
7#[derive(Clone)]
9pub struct Topic<M: ActorMessage> {
10 name: String,
11 id: Uuid,
12 _phantom: PhantomData<M>,
13}
14impl<M: ActorMessage> Topic<M> {
15 pub fn new(name: impl Into<String>) -> Self {
16 Topic {
17 name: name.into(),
18 id: Uuid::new_v4(),
19 _phantom: PhantomData,
20 }
21 }
22
23 pub fn name(&self) -> &str {
24 &self.name
25 }
26
27 pub fn id(&self) -> Uuid {
28 self.id
29 }
30
31 pub fn type_id(&self) -> TypeId {
32 TypeId::of::<M>()
33 }
34}
35
36impl<M: ActorMessage> Debug for Topic<M> {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.debug_struct("Topic")
39 .field("name", &self.name)
40 .field("id", &self.id)
41 .finish()
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use std::any::TypeId;
49
50 #[derive(Debug, Clone)]
52 struct TestMessage {
53 _content: String,
54 }
55 impl ActorMessage for TestMessage {}
56
57 #[derive(Debug)]
58 struct AnotherTestMessage {
59 _data: i32,
60 }
61 impl ActorMessage for AnotherTestMessage {}
62
63 #[test]
64 fn test_topic_creation_with_string() {
65 let topic = Topic::<TestMessage>::new("test_topic");
66
67 assert_eq!(topic.name(), "test_topic");
68 assert!(!topic.id().is_nil());
69 }
70
71 #[test]
72 fn test_topic_creation_with_str() {
73 let topic = Topic::<TestMessage>::new("str_topic");
74
75 assert_eq!(topic.name(), "str_topic");
76 assert!(!topic.id().is_nil());
77 }
78
79 #[test]
80 fn test_topic_unique_ids() {
81 let topic1 = Topic::<TestMessage>::new("topic1");
82 let topic2 = Topic::<TestMessage>::new("topic2");
83
84 assert_ne!(topic1.id(), topic2.id());
85 }
86
87 #[test]
88 fn test_topic_same_name_different_ids() {
89 let topic1 = Topic::<TestMessage>::new("same_name");
90 let topic2 = Topic::<TestMessage>::new("same_name");
91
92 assert_eq!(topic1.name(), topic2.name());
93 assert_ne!(topic1.id(), topic2.id());
94 }
95
96 #[test]
97 fn test_topic_type_id_same_type() {
98 let topic1 = Topic::<TestMessage>::new("topic1");
99 let topic2 = Topic::<TestMessage>::new("topic2");
100
101 assert_eq!(topic1.type_id(), topic2.type_id());
102 assert_eq!(topic1.type_id(), TypeId::of::<TestMessage>());
103 }
104
105 #[test]
106 fn test_topic_type_id_different_types() {
107 let topic1 = Topic::<TestMessage>::new("topic1");
108 let topic2 = Topic::<AnotherTestMessage>::new("topic2");
109
110 assert_ne!(topic1.type_id(), topic2.type_id());
111 assert_eq!(topic1.type_id(), TypeId::of::<TestMessage>());
112 assert_eq!(topic2.type_id(), TypeId::of::<AnotherTestMessage>());
113 }
114
115 #[test]
116 fn test_topic_clone() {
117 let original = Topic::<TestMessage>::new("original_topic");
118 let cloned = original.clone();
119
120 assert_eq!(original.name(), cloned.name());
121 assert_eq!(original.id(), cloned.id());
122 assert_eq!(original.type_id(), cloned.type_id());
123 }
124
125 #[test]
126 fn test_topic_debug() {
127 let topic = Topic::<TestMessage>::new("debug_topic");
128 let debug_str = format!("{topic:?}");
129
130 assert!(debug_str.contains("Topic"));
131 assert!(debug_str.contains("debug_topic"));
132 assert!(debug_str.contains("name"));
133 assert!(debug_str.contains("id"));
134 }
135
136 #[test]
137 fn test_topic_name_accessor() {
138 let topic = Topic::<TestMessage>::new("accessor_test");
139
140 assert_eq!(topic.name(), "accessor_test");
141 }
142
143 #[test]
144 fn test_topic_id_accessor() {
145 let topic = Topic::<TestMessage>::new("id_test");
146 let id = topic.id();
147
148 assert!(!id.is_nil());
149 assert_eq!(topic.id(), id); }
151
152 #[test]
153 fn test_topic_type_id_accessor() {
154 let topic = Topic::<TestMessage>::new("type_id_test");
155 let type_id = topic.type_id();
156
157 assert_eq!(type_id, TypeId::of::<TestMessage>());
158 assert_eq!(topic.type_id(), type_id); }
160
161 #[test]
162 fn test_topic_with_empty_name() {
163 let topic = Topic::<TestMessage>::new("");
164
165 assert_eq!(topic.name(), "");
166 assert!(!topic.id().is_nil());
167 }
168
169 #[test]
170 fn test_topic_with_unicode_name() {
171 let topic = Topic::<TestMessage>::new("テスト_トピック_🚀");
172
173 assert_eq!(topic.name(), "テスト_トピック_🚀");
174 assert!(!topic.id().is_nil());
175 }
176
177 #[test]
178 fn test_topic_with_long_name() {
179 let long_name = "a".repeat(1000);
180 let topic = Topic::<TestMessage>::new(long_name.clone());
181
182 assert_eq!(topic.name(), long_name);
183 assert!(!topic.id().is_nil());
184 }
185
186 #[test]
187 fn test_topic_type_safety() {
188 let _topic1: Topic<TestMessage> = Topic::new("test");
190 let _topic2: Topic<AnotherTestMessage> = Topic::new("test");
191
192 }
195
196 #[test]
197 fn test_topic_phantom_data() {
198 let topic = Topic::<TestMessage>::new("phantom_test");
200
201 assert_eq!(std::mem::size_of_val(&topic._phantom), 0);
203 }
204}