open_dis_rust/
simulation_management.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2025 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7//! The Simulation Management (SIMAN) protocol family
8
9use crate::common::data_types::ClockTime;
10use crate::common::data_types::datum_records::{FixedDatumRecord, VariableDatumRecord};
11use crate::common::enums::{ActionResponseRequestStatus, EventType, FrozenBehavior, Reason};
12use crate::common::generic_header::GenericHeader;
13use crate::{
14    common::{
15        SerializedLength,
16        data_types::entity_id::EntityId,
17        enums::{AcknowledgeFlag, AcknowledgeResponseFlag, PduType, ProtocolFamily},
18        pdu::Pdu,
19        pdu_header::PduHeader,
20    },
21    define_pdu,
22};
23
24define_pdu! {
25    #[derive(Debug)]
26    /// Implemented according to IEEE 1278.1-2012 §7.5.2
27    pub struct CreateEntityPdu {
28        header: PduHeader,
29        pdu_type: PduType::CreateEntity,
30        protocol_family: ProtocolFamily::SimulationManagement,
31        fields: {
32            pub originating_entity_id: EntityId,
33            pub receiving_entity_id: EntityId,
34            pub request_id: u32,
35        }
36    }
37}
38
39define_pdu! {
40    #[derive(Debug)]
41    /// Implemented according to IEEE 1278.1-2012 §7.5.3
42    pub struct RemoveEntityPdu {
43        header: PduHeader,
44        pdu_type: PduType::RemoveEntity,
45        protocol_family: ProtocolFamily::SimulationManagement,
46        fields: {
47            pub originating_entity_id: EntityId,
48            pub receiving_entity_id: EntityId,
49            pub request_id: u32,
50        }
51    }
52}
53
54define_pdu! {
55    #[derive(Debug)]
56    /// Implemented according to IEEE 1278.1-2012 §7.5.4
57    pub struct StartResumePdu {
58        header: PduHeader,
59        pdu_type: PduType::StartResume,
60        protocol_family: ProtocolFamily::SimulationManagement,
61        fields: {
62            pub originating_entity_id: EntityId,
63            pub receiving_entity_id: EntityId,
64            pub real_world_time: ClockTime,
65            pub simulation_time: ClockTime,
66            pub request_id: u32,
67        }
68    }
69}
70
71define_pdu! {
72    #[derive(Debug)]
73    /// Implemented according to IEEE 1278.1-2012 §7.5.5
74    pub struct StopFreezePdu {
75        header: PduHeader,
76        pdu_type: PduType::StopFreeze,
77        protocol_family: ProtocolFamily::SimulationManagement,
78        fields: {
79            pub originating_entity_id: EntityId,
80            pub receiving_entity_id: EntityId,
81            pub real_world_time: ClockTime,
82            pub reason: Reason,
83            pub frozen_behavior: FrozenBehavior,
84            padding: u16,
85            pub request_id: u32,
86        }
87    }
88}
89
90define_pdu! {
91    #[derive(Debug)]
92    /// Implemented according to IEEE 1278.1-2012 §7.5.6
93    pub struct AcknowledgePdu {
94        header: PduHeader,
95        pdu_type: PduType::Acknowledge,
96        protocol_family: ProtocolFamily::SimulationManagement,
97        fields: {
98            pub originating_entity_id: EntityId,
99            pub receiving_entity_id: EntityId,
100            pub acknowledge_flag: AcknowledgeFlag,
101            pub response_flag: AcknowledgeResponseFlag,
102            pub request_id: u32,
103        }
104    }
105}
106
107define_pdu! {
108    #[derive(Debug)]
109    /// Implemented according to IEEE 1278.1-2012 §7.5.7
110    pub struct ActionRequestPdu {
111        header: PduHeader,
112        pdu_type: PduType::ActionRequest,
113        protocol_family: ProtocolFamily::SimulationManagement,
114        fields: {
115            pub originating_entity_id: EntityId,
116            pub receiving_entity_id: EntityId,
117            pub request_id: u32,
118            pub action_id: u32,
119            pub number_of_fixed_datum_records: u32,
120            pub number_of_variable_datum_records: u32,
121            pub fixed_datum_records: Vec<FixedDatumRecord>,
122            pub variable_datum_records: Vec<VariableDatumRecord>,
123        }
124    }
125}
126
127define_pdu! {
128    #[derive(Debug)]
129    /// Implemented according to IEEE 1278.1-2012 §7.5.8
130    pub struct ActionResponsePdu {
131        header: PduHeader,
132        pdu_type: PduType::ActionResponse,
133        protocol_family: ProtocolFamily::SimulationManagement,
134        fields: {
135            pub originating_entity_id: EntityId,
136            pub receiving_entity_id: EntityId,
137            pub request_id: u32,
138            pub request_status: ActionResponseRequestStatus,
139            pub number_of_fixed_datum_records: u32,
140            pub number_of_variable_datum_records: u32,
141            pub fixed_datum_records: Vec<FixedDatumRecord>,
142            pub variable_datum_records: Vec<VariableDatumRecord>,
143        }
144    }
145}
146
147define_pdu! {
148    #[derive(Debug)]
149    /// Implemented according to IEEE 1278.1-2012 §7.5.9
150    pub struct DataQueryPdu {
151        header: PduHeader,
152        pdu_type: PduType::DataQuery,
153        protocol_family: ProtocolFamily::SimulationManagement,
154        fields: {
155            pub originating_entity_id: EntityId,
156            pub receiving_entity_id: EntityId,
157            pub request_id: u32,
158            pub time_interval: u32,
159            pub number_of_fixed_datum_records: u32,
160            pub number_of_variable_datum_records: u32,
161            pub fixed_datum_records: Vec<FixedDatumRecord>,
162            pub variable_datum_records: Vec<VariableDatumRecord>,
163        }
164    }
165}
166
167define_pdu! {
168    #[derive(Debug)]
169    /// Implemented according to IEEE 1278.1-2012 §7.5.10
170    pub struct SetDataPdu {
171        header: PduHeader,
172        pdu_type: PduType::SetData,
173        protocol_family: ProtocolFamily::SimulationManagement,
174        fields: {
175            pub originating_entity_id: EntityId,
176            pub receiving_entity_id: EntityId,
177            pub request_id: u32,
178            padding: u32,
179            pub number_of_fixed_datum_records: u32,
180            pub number_of_variable_datum_records: u32,
181            pub fixed_datum_records: Vec<FixedDatumRecord>,
182            pub variable_datum_records: Vec<VariableDatumRecord>,
183        }
184    }
185}
186
187define_pdu! {
188    #[derive(Debug)]
189    /// Implemented according to IEEE 1278.1-2012 §7.5.11
190    pub struct DataPdu {
191        header: PduHeader,
192        pdu_type: PduType::Data,
193        protocol_family: ProtocolFamily::SimulationManagement,
194        fields: {
195            pub originating_entity_id: EntityId,
196            pub receiving_entity_id: EntityId,
197            pub request_id: u32,
198            padding: u32,
199            pub number_of_fixed_datum_records: u32,
200            pub number_of_variable_datum_records: u32,
201            pub fixed_datum_records: Vec<FixedDatumRecord>,
202            pub variable_datum_records: Vec<VariableDatumRecord>,
203        }
204    }
205}
206
207define_pdu! {
208    #[derive(Debug)]
209    /// Implemented according to IEEE 1278.1-2012 §7.5.12
210    pub struct EventReportPdu {
211        header: PduHeader,
212        pdu_type: PduType::EventReport,
213        protocol_family: ProtocolFamily::SimulationManagement,
214        fields: {
215            pub originating_entity_id: EntityId,
216            pub receiving_entity_id: EntityId,
217            pub event_type: EventType,
218            padding: u32,
219            pub number_of_fixed_datum_records: u32,
220            pub number_of_variable_datum_records: u32,
221            pub fixed_datum_records: Vec<FixedDatumRecord>,
222            pub variable_datum_records: Vec<VariableDatumRecord>,
223        }
224    }
225}
226
227define_pdu! {
228    #[derive(Debug)]
229    /// Implemented according to IEEE 1278.1-2012 §7.5.13
230    pub struct CommentPdu {
231        header: PduHeader,
232        pdu_type: PduType::Comment,
233        protocol_family: ProtocolFamily::SimulationManagement,
234        fields: {
235            pub originating_entity_id: EntityId,
236            pub receiving_entity_id: EntityId,
237            pub number_of_fixed_datum_records: u32,
238            pub number_of_variable_datum_records: u32,
239            pub fixed_datum_records: Vec<FixedDatumRecord>,
240            pub variable_datum_records: Vec<VariableDatumRecord>,
241        }
242    }
243}
244
245#[cfg(test)]
246mod tests {
247    use super::*;
248    use crate::common::{constants::BITS_PER_BYTE, pdu::Pdu};
249    use bytes::BytesMut;
250
251    mod create_entity_pdu_tests {
252        use super::*;
253        #[test]
254        fn cast_to_any() {
255            let pdu = CreateEntityPdu::new();
256            let any_pdu = pdu.as_any();
257
258            assert!(any_pdu.is::<CreateEntityPdu>());
259        }
260
261        #[test]
262        fn serialize_then_deserialize() {
263            let mut pdu = CreateEntityPdu::new();
264            let mut serialize_buf = BytesMut::new();
265            let _ = pdu.serialize(&mut serialize_buf);
266
267            let mut deserialize_buf = serialize_buf.freeze();
268            let new_pdu = CreateEntityPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
269            assert_eq!(new_pdu.header, pdu.header);
270        }
271
272        #[test]
273        fn check_default_pdu_length() {
274            const DEFAULT_LENGTH: u16 = 224 / BITS_PER_BYTE;
275            let pdu = CreateEntityPdu::new();
276            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
277        }
278    }
279
280    mod remove_entity_pdu_tests {
281        use super::*;
282
283        #[test]
284        fn cast_to_any() {
285            let pdu = RemoveEntityPdu::new();
286            let any_pdu = pdu.as_any();
287
288            assert!(any_pdu.is::<RemoveEntityPdu>());
289        }
290
291        #[test]
292        fn serialize_then_deserialize() {
293            let mut pdu = RemoveEntityPdu::new();
294            let mut serialize_buf = BytesMut::new();
295            let _ = pdu.serialize(&mut serialize_buf);
296
297            let mut deserialize_buf = serialize_buf.freeze();
298            let new_pdu = RemoveEntityPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
299            assert_eq!(new_pdu.header, pdu.header);
300        }
301
302        #[test]
303        fn check_default_pdu_length() {
304            const DEFAULT_LENGTH: u16 = 224 / BITS_PER_BYTE;
305            let pdu = RemoveEntityPdu::new();
306            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
307        }
308    }
309
310    mod stop_freeze_pdu_tests {
311        use super::*;
312
313        #[test]
314        fn cast_to_any() {
315            let pdu = StopFreezePdu::new();
316            let any_pdu = pdu.as_any();
317
318            assert!(any_pdu.is::<StopFreezePdu>());
319        }
320
321        #[test]
322        fn serialize_then_deserialize() {
323            let mut pdu = StopFreezePdu::new();
324            let mut serialize_buf = BytesMut::new();
325            let _ = pdu.serialize(&mut serialize_buf);
326
327            let mut deserialize_buf = serialize_buf.freeze();
328            let new_pdu = StopFreezePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
329            assert_eq!(new_pdu.header, pdu.header);
330        }
331
332        #[test]
333        fn check_default_pdu_length() {
334            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
335            let pdu = StopFreezePdu::new();
336            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
337        }
338    }
339
340    mod start_resume_pdu_tests {
341        use super::*;
342
343        #[test]
344        fn cast_to_any() {
345            let pdu = StartResumePdu::new();
346            let any_pdu = pdu.as_any();
347
348            assert!(any_pdu.is::<StartResumePdu>());
349        }
350
351        #[test]
352        fn serialize_then_deserialize() {
353            let mut pdu = StartResumePdu::new();
354            let mut serialize_buf = BytesMut::new();
355            let _ = pdu.serialize(&mut serialize_buf);
356
357            let mut deserialize_buf = serialize_buf.freeze();
358            let new_pdu = StartResumePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
359            assert_eq!(new_pdu.header, pdu.header);
360        }
361
362        #[test]
363        fn check_default_pdu_length() {
364            const DEFAULT_LENGTH: u16 = 352 / BITS_PER_BYTE;
365            let pdu = StartResumePdu::new();
366            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
367        }
368    }
369
370    mod acknowledge_pdu_tests {
371        use super::*;
372
373        #[test]
374        fn cast_to_any() {
375            let pdu = AcknowledgePdu::new();
376            let any_pdu = pdu.as_any();
377
378            assert!(any_pdu.is::<AcknowledgePdu>());
379        }
380
381        #[test]
382        fn serialize_then_deserialize() {
383            let mut pdu = AcknowledgePdu::new();
384            let mut serialize_buf = BytesMut::new();
385            let _ = pdu.serialize(&mut serialize_buf);
386
387            let mut deserialize_buf = serialize_buf.freeze();
388            let new_pdu = AcknowledgePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
389            assert_eq!(new_pdu.header, pdu.header);
390        }
391
392        #[test]
393        fn check_default_pdu_length() {
394            const DEFAULT_LENGTH: u16 = 256 / BITS_PER_BYTE;
395            let pdu = AcknowledgePdu::new();
396            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
397        }
398    }
399
400    mod action_request_pdu_tests {
401        use super::*;
402
403        #[test]
404        fn cast_to_any() {
405            let pdu = ActionRequestPdu::new();
406            let any_pdu = pdu.as_any();
407
408            assert!(any_pdu.is::<ActionRequestPdu>());
409        }
410
411        #[test]
412        fn serialize_then_deserialize() {
413            let mut pdu = ActionRequestPdu::new();
414            let mut serialize_buf = BytesMut::new();
415            let _ = pdu.serialize(&mut serialize_buf);
416
417            let mut deserialize_buf = serialize_buf.freeze();
418            let new_pdu = ActionRequestPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
419            assert_eq!(new_pdu.header, pdu.header);
420        }
421
422        #[test]
423        fn check_default_pdu_length() {
424            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
425            let pdu = ActionRequestPdu::new();
426            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
427        }
428    }
429
430    mod action_response_pdu_tests {
431        use super::*;
432        #[test]
433        fn cast_to_any() {
434            let pdu = ActionResponsePdu::new();
435            let any_pdu = pdu.as_any();
436
437            assert!(any_pdu.is::<ActionResponsePdu>());
438        }
439
440        #[test]
441        fn serialize_then_deserialize() {
442            let mut pdu = ActionResponsePdu::new();
443            let mut serialize_buf = BytesMut::new();
444            let _ = pdu.serialize(&mut serialize_buf);
445
446            let mut deserialize_buf = serialize_buf.freeze();
447            let new_pdu = ActionResponsePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
448            assert_eq!(new_pdu.header, pdu.header);
449        }
450
451        #[test]
452        fn check_default_pdu_length() {
453            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
454            let pdu = ActionResponsePdu::new();
455            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
456        }
457    }
458
459    mod data_pdu_tests {
460        use super::*;
461
462        #[test]
463        fn cast_to_any() {
464            let pdu = DataPdu::new();
465            let any_pdu = pdu.as_any();
466
467            assert!(any_pdu.is::<DataPdu>());
468        }
469
470        #[test]
471        fn serialize_then_deserialize() {
472            let mut pdu = DataPdu::new();
473            let mut serialize_buf = BytesMut::new();
474            let _ = pdu.serialize(&mut serialize_buf);
475
476            let mut deserialize_buf = serialize_buf.freeze();
477            let new_pdu = DataPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
478            assert_eq!(new_pdu.header, pdu.header);
479        }
480
481        #[test]
482        fn check_default_pdu_length() {
483            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
484            let pdu = DataPdu::new();
485            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
486        }
487    }
488
489    mod set_data_pdu_tests {
490        use super::*;
491
492        #[test]
493        fn cast_to_any() {
494            let pdu = SetDataPdu::new();
495            let any_pdu = pdu.as_any();
496
497            assert!(any_pdu.is::<SetDataPdu>());
498        }
499
500        #[test]
501        fn serialize_then_deserialize() {
502            let mut pdu = SetDataPdu::new();
503            let mut serialize_buf = BytesMut::new();
504            let _ = pdu.serialize(&mut serialize_buf);
505
506            let mut deserialize_buf = serialize_buf.freeze();
507            let new_pdu = SetDataPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
508            assert_eq!(new_pdu.header, pdu.header);
509        }
510
511        #[test]
512        fn check_default_pdu_length() {
513            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
514            let pdu = SetDataPdu::new();
515            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
516        }
517    }
518
519    mod data_query_pdu_tests {
520        use super::*;
521
522        #[test]
523        fn cast_to_any() {
524            let pdu = DataQueryPdu::new();
525            let any_pdu = pdu.as_any();
526
527            assert!(any_pdu.is::<DataQueryPdu>());
528        }
529
530        #[test]
531        fn serialize_then_deserialize() {
532            let mut pdu = DataQueryPdu::new();
533            let mut serialize_buf = BytesMut::new();
534            let _ = pdu.serialize(&mut serialize_buf);
535
536            let mut deserialize_buf = serialize_buf.freeze();
537            let new_pdu = DataQueryPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
538            assert_eq!(new_pdu.header, pdu.header);
539        }
540
541        #[test]
542        fn check_default_pdu_length() {
543            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
544            let pdu = DataQueryPdu::new();
545            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
546        }
547    }
548
549    mod event_report_pdu_tests {
550        use super::*;
551
552        #[test]
553        fn cast_to_any() {
554            let pdu = EventReportPdu::new();
555            let any_pdu = pdu.as_any();
556
557            assert!(any_pdu.is::<EventReportPdu>());
558        }
559
560        #[test]
561        fn serialize_then_deserialize() {
562            let mut pdu = EventReportPdu::new();
563            let mut serialize_buf = BytesMut::new();
564            let _ = pdu.serialize(&mut serialize_buf);
565
566            let mut deserialize_buf = serialize_buf.freeze();
567            let new_pdu = EventReportPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
568            assert_eq!(new_pdu.header, pdu.header);
569        }
570
571        #[test]
572        fn check_default_pdu_length() {
573            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
574            let pdu = EventReportPdu::new();
575            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
576        }
577    }
578
579    mod comment_pdu_tests {
580        use super::*;
581        #[test]
582        fn cast_to_any() {
583            let pdu = CommentPdu::new();
584            let any_pdu = pdu.as_any();
585
586            assert!(any_pdu.is::<CommentPdu>());
587        }
588
589        #[test]
590        fn serialize_then_deserialize() {
591            let mut pdu = CommentPdu::new();
592            let mut serialize_buf = BytesMut::new();
593            let _ = pdu.serialize(&mut serialize_buf);
594
595            let mut deserialize_buf = serialize_buf.freeze();
596            let new_pdu = CommentPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
597            assert_eq!(new_pdu.header, pdu.header);
598        }
599
600        #[test]
601        fn check_default_pdu_length() {
602            const DEFAULT_LENGTH: u16 = 256 / BITS_PER_BYTE;
603            let pdu = CommentPdu::new();
604            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
605        }
606    }
607}