open_dis_rust/
information_operations.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 Information Operations protocol family
8
9use crate::common::enums::{
10    IOActionIOActionPhase, IOActionIOActionType, IOActionIOSimulationSource, IOActionIOWarfareType,
11    IOReportIOReportType, PduType, ProtocolFamily,
12};
13use crate::common::generic_header::GenericHeader;
14use crate::common::{
15    SerializedLength,
16    data_types::{
17        SimulationIdentifier, entity_id::EntityId,
18        standard_variable_specification::StandardVariableSpecification,
19    },
20    pdu::Pdu,
21    pdu_header::PduHeader,
22};
23use crate::define_pdu;
24
25define_pdu! {
26    #[derive(Debug)]
27    /// Implemented according to IEEE 1278.1-2012 §7.12.3
28    pub struct InformationOperationsReportPdu {
29        header: PduHeader,
30        pdu_type: PduType::InformationOperationsReport,
31        protocol_family: ProtocolFamily::InformationOperations,
32        fields: {
33            pub originating_simulation_id: SimulationIdentifier,
34            pub io_simulation_source: IOActionIOSimulationSource,
35            pub io_report_type: IOReportIOReportType,
36            padding: u8,
37            pub io_attacker_entity_id: EntityId,
38            pub primary_target_entity_id: EntityId,
39            padding2: u16,
40            padding3: u16,
41            pub io_records: StandardVariableSpecification,
42        }
43    }
44}
45
46define_pdu! {
47    #[derive(Debug)]
48    /// Implemented according to IEEE 1278.1-2012 §7.12.2
49    pub struct InformationOperationsActionPdu {
50        header: PduHeader,
51        pdu_type: PduType::InformationOperationsAction,
52        protocol_family: ProtocolFamily::InformationOperations,
53        fields: {
54            pub originating_simulation_id: SimulationIdentifier,
55            pub receiving_simulation_id: SimulationIdentifier,
56            pub request_id: u32,
57            pub io_warfare_type: IOActionIOWarfareType,
58            pub io_simulation_source: IOActionIOSimulationSource,
59            pub io_action_type: IOActionIOActionType,
60            pub io_action_phase: IOActionIOActionPhase,
61            padding: u32,
62            pub io_attacker_entity_id: EntityId,
63            pub io_primary_target_entity_id: EntityId,
64            padding2: u16,
65            pub io_records: StandardVariableSpecification,
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    mod information_operations_actions_pdu {
73        use crate::{
74            common::{constants::BITS_PER_BYTE, pdu::Pdu},
75            information_operations::InformationOperationsActionPdu,
76        };
77        use bytes::BytesMut;
78        #[test]
79        fn cast_to_any() {
80            let pdu = InformationOperationsActionPdu::new();
81            let any_pdu = pdu.as_any();
82
83            assert!(any_pdu.is::<InformationOperationsActionPdu>());
84        }
85
86        #[test]
87        fn serialize_then_deserialize() {
88            let mut pdu = InformationOperationsActionPdu::new();
89            let mut serialize_buf = BytesMut::new();
90            let _ = pdu.serialize(&mut serialize_buf);
91
92            let mut deserialize_buf = serialize_buf.freeze();
93            let new_pdu =
94                InformationOperationsActionPdu::deserialize(&mut deserialize_buf).expect("Some");
95            assert_eq!(new_pdu.header, pdu.header);
96        }
97
98        #[test]
99        fn check_default_pdu_length() {
100            const DEFAULT_LENGTH: u16 = 448 / BITS_PER_BYTE;
101            let pdu = InformationOperationsActionPdu::new();
102            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
103        }
104    }
105
106    mod information_operations_report_pdu {
107        use crate::{
108            common::{constants::BITS_PER_BYTE, pdu::Pdu},
109            information_operations::InformationOperationsReportPdu,
110        };
111        use bytes::BytesMut;
112
113        #[test]
114        fn cast_to_any() {
115            let pdu = InformationOperationsReportPdu::new();
116            let any_pdu = pdu.as_any();
117
118            assert!(any_pdu.is::<InformationOperationsReportPdu>());
119        }
120
121        #[test]
122        fn serialize_then_deserialize() {
123            let mut pdu = InformationOperationsReportPdu::new();
124            let mut serialize_buf = BytesMut::new();
125            let _ = pdu.serialize(&mut serialize_buf);
126
127            let mut deserialize_buf = serialize_buf.freeze();
128            let new_pdu =
129                InformationOperationsReportPdu::deserialize(&mut deserialize_buf).expect("Some");
130            assert_eq!(new_pdu.header, pdu.header);
131        }
132
133        #[test]
134        fn check_default_pdu_length() {
135            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
136            let pdu = InformationOperationsReportPdu::new();
137            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
138        }
139    }
140}