galeon_engine/
protocol.rs1use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub enum ProtocolKind {
30 Command,
32 Query,
34 Event,
36 Dto,
38}
39
40pub trait ProtocolMeta {
56 fn name() -> &'static str;
58
59 fn kind() -> ProtocolKind;
61}
62
63pub trait Command: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static {}
73
74pub trait ProtocolQuery: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static {}
85
86pub trait Event: Serialize + for<'de> Deserialize<'de> + Send + Sync + 'static {}
95
96pub trait Dto: Serialize + for<'de> Deserialize<'de> + Clone + Send + Sync + 'static {}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[derive(Debug, Serialize, Deserialize, PartialEq)]
114 struct SpawnUnit {
115 unit_id: u64,
116 location_id: u64,
117 }
118 impl Command for SpawnUnit {}
119 impl ProtocolMeta for SpawnUnit {
120 fn name() -> &'static str {
121 "SpawnUnit"
122 }
123 fn kind() -> ProtocolKind {
124 ProtocolKind::Command
125 }
126 }
127
128 #[derive(Debug, Serialize, Deserialize, PartialEq)]
129 struct GetWorldSnapshot;
130 impl ProtocolQuery for GetWorldSnapshot {}
131 impl ProtocolMeta for GetWorldSnapshot {
132 fn name() -> &'static str {
133 "GetWorldSnapshot"
134 }
135 fn kind() -> ProtocolKind {
136 ProtocolKind::Query
137 }
138 }
139
140 #[derive(Debug, Serialize, Deserialize, PartialEq)]
141 struct UnitDestroyed {
142 unit_id: u64,
143 arrived_at: u64,
144 }
145 impl Event for UnitDestroyed {}
146 impl ProtocolMeta for UnitDestroyed {
147 fn name() -> &'static str {
148 "UnitDestroyed"
149 }
150 fn kind() -> ProtocolKind {
151 ProtocolKind::Event
152 }
153 }
154
155 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
156 struct WorldSnapshot {
157 unit_count: u32,
158 }
159 impl Dto for WorldSnapshot {}
160 impl ProtocolMeta for WorldSnapshot {
161 fn name() -> &'static str {
162 "WorldSnapshot"
163 }
164 fn kind() -> ProtocolKind {
165 ProtocolKind::Dto
166 }
167 }
168
169 #[test]
172 fn protocol_kind_variants() {
173 assert_ne!(ProtocolKind::Command, ProtocolKind::Query);
174 assert_ne!(ProtocolKind::Event, ProtocolKind::Dto);
175 }
176
177 #[test]
178 fn protocol_kind_serde_roundtrip() {
179 for kind in [
180 ProtocolKind::Command,
181 ProtocolKind::Query,
182 ProtocolKind::Event,
183 ProtocolKind::Dto,
184 ] {
185 let json = serde_json::to_string(&kind).unwrap();
186 let back: ProtocolKind = serde_json::from_str(&json).unwrap();
187 assert_eq!(kind, back);
188 }
189 }
190
191 #[test]
194 fn protocol_meta_command() {
195 assert_eq!(SpawnUnit::name(), "SpawnUnit");
196 assert_eq!(SpawnUnit::kind(), ProtocolKind::Command);
197 }
198
199 #[test]
200 fn protocol_meta_query() {
201 assert_eq!(GetWorldSnapshot::name(), "GetWorldSnapshot");
202 assert_eq!(GetWorldSnapshot::kind(), ProtocolKind::Query);
203 }
204
205 #[test]
206 fn protocol_meta_event() {
207 assert_eq!(UnitDestroyed::name(), "UnitDestroyed");
208 assert_eq!(UnitDestroyed::kind(), ProtocolKind::Event);
209 }
210
211 #[test]
212 fn protocol_meta_dto() {
213 assert_eq!(WorldSnapshot::name(), "WorldSnapshot");
214 assert_eq!(WorldSnapshot::kind(), ProtocolKind::Dto);
215 }
216
217 #[test]
220 fn command_serde_roundtrip() {
221 let cmd = SpawnUnit {
222 unit_id: 1,
223 location_id: 42,
224 };
225 let json = serde_json::to_string(&cmd).unwrap();
226 let back: SpawnUnit = serde_json::from_str(&json).unwrap();
227 assert_eq!(cmd, back);
228 }
229
230 #[test]
231 fn query_serde_roundtrip() {
232 let q = GetWorldSnapshot;
233 let json = serde_json::to_string(&q).unwrap();
234 let back: GetWorldSnapshot = serde_json::from_str(&json).unwrap();
235 assert_eq!(q, back);
236 }
237
238 #[test]
239 fn event_serde_roundtrip() {
240 let evt = UnitDestroyed {
241 unit_id: 1,
242 arrived_at: 1000,
243 };
244 let json = serde_json::to_string(&evt).unwrap();
245 let back: UnitDestroyed = serde_json::from_str(&json).unwrap();
246 assert_eq!(evt, back);
247 }
248
249 #[test]
250 fn dto_serde_roundtrip() {
251 let dto = WorldSnapshot { unit_count: 5 };
252 let json = serde_json::to_string(&dto).unwrap();
253 let back: WorldSnapshot = serde_json::from_str(&json).unwrap();
254 assert_eq!(dto, back);
255 }
256
257 #[test]
260 fn component_and_command_no_conflict() {
261 use crate::component::Component;
262
263 #[derive(Debug, Serialize, Deserialize)]
264 struct Health {
265 hp: u32,
266 }
267 impl Component for Health {}
268 impl Command for Health {}
269 impl ProtocolMeta for Health {
270 fn name() -> &'static str {
271 "Health"
272 }
273 fn kind() -> ProtocolKind {
274 ProtocolKind::Command
275 }
276 }
277
278 let h = Health { hp: 100 };
280 assert_eq!(Health::kind(), ProtocolKind::Command);
281 let json = serde_json::to_string(&h).unwrap();
282 assert!(json.contains("100"));
283 }
284}