open_dis_rust/information_operations/
information_operations_action_pdu.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2023 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7use bytes::{Buf, BufMut, BytesMut};
8use std::any::Any;
9
10use crate::{
11    common::{
12        dis_error::DISError,
13        entity_id::EntityId,
14        enums::{
15            IOActionIOActionPhase, IOActionIOActionType, IOActionIOSimulationSource,
16            IOActionIOWarfareType,
17        },
18        pdu::Pdu,
19        pdu_header::{PduHeader, PduType, ProtocolFamily},
20    },
21    warfare::data_types::standard_variable_specification::StandardVariableSpecification,
22};
23
24#[derive(Clone, Debug)]
25/// Implemented according to IEEE 1278.1-2012 ยง7.12.2
26pub struct InformationOperationsActionPdu {
27    pub pdu_header: PduHeader,
28    pub originating_simulation_id: EntityId,
29    pub receiving_simulation_id: EntityId,
30    pub request_id: u32,
31    pub io_warfare_type: IOActionIOWarfareType,
32    pub io_simulation_source: IOActionIOSimulationSource,
33    pub io_action_type: IOActionIOActionType,
34    pub io_action_phase: IOActionIOActionPhase,
35    pub padding1: u32,
36    pub io_attacker_entity_id: EntityId,
37    pub io_primary_target_entity_id: EntityId,
38    pub padding2: u16,
39    pub io_records: StandardVariableSpecification,
40}
41
42impl Default for InformationOperationsActionPdu {
43    /// Creates default-initialized Information Operations Action PDU
44    ///
45    /// # Examples
46    ///
47    /// Initializing an Information Operations Action PDU:
48    /// ```
49    /// use open_dis_rust::information_operations::information_operations_action_pdu::InformationOperationsActionPdu;
50    /// let mut io_action_pdu = InformationOperationsActionPdu::default();
51    /// ```
52    ///
53    fn default() -> Self {
54        InformationOperationsActionPdu {
55            pdu_header: PduHeader::default(
56                PduType::InformationOperationsAction,
57                ProtocolFamily::InformationOperations,
58                32,
59            ),
60            originating_simulation_id: EntityId::default(1),
61            receiving_simulation_id: EntityId::default(2),
62            request_id: 0,
63            io_warfare_type: IOActionIOWarfareType::default(),
64            io_simulation_source: IOActionIOSimulationSource::default(),
65            io_action_type: IOActionIOActionType::default(),
66            io_action_phase: IOActionIOActionPhase::default(),
67            padding1: 0,
68            io_attacker_entity_id: EntityId::default(3),
69            io_primary_target_entity_id: EntityId::default(4),
70            padding2: 0,
71            io_records: StandardVariableSpecification::default(),
72        }
73    }
74}
75
76impl Pdu for InformationOperationsActionPdu {
77    fn serialize(&mut self, buf: &mut BytesMut) {
78        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
79            .expect("The length of the PDU should fit in a u16.");
80        self.pdu_header.serialize(buf);
81        self.originating_simulation_id.serialize(buf);
82        self.receiving_simulation_id.serialize(buf);
83        buf.put_u32(self.request_id);
84        buf.put_u8(self.io_warfare_type as u8);
85        buf.put_u8(self.io_simulation_source as u8);
86        buf.put_u8(self.io_action_type as u8);
87        buf.put_u8(self.io_action_phase as u8);
88        buf.put_u32(self.padding1);
89        self.io_attacker_entity_id.serialize(buf);
90        self.io_primary_target_entity_id.serialize(buf);
91        buf.put_u16(self.padding2);
92        self.io_records.serialize(buf);
93    }
94
95    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
96    where
97        Self: Sized,
98    {
99        let pdu_header = PduHeader::deserialize(&mut buffer);
100        if pdu_header.pdu_type == PduType::InformationOperationsAction {
101            let originating_simulation_id = EntityId::deserialize(&mut buffer);
102            let receiving_simulation_id = EntityId::deserialize(&mut buffer);
103            let request_id = buffer.get_u32();
104            let io_warfare_type = IOActionIOWarfareType::deserialize(&mut buffer);
105            let io_simulation_source = IOActionIOSimulationSource::deserialize(&mut buffer);
106            let io_action_type = IOActionIOActionType::deserialize(&mut buffer);
107            let io_action_phase = IOActionIOActionPhase::deserialize(&mut buffer);
108            let padding1 = buffer.get_u32();
109            let io_attacker_entity_id = EntityId::deserialize(&mut buffer);
110            let io_primary_target_entity_id = EntityId::deserialize(&mut buffer);
111            let padding2 = buffer.get_u16();
112            let io_records = StandardVariableSpecification::deserialize(&mut buffer);
113            Ok(InformationOperationsActionPdu {
114                pdu_header,
115                originating_simulation_id,
116                receiving_simulation_id,
117                request_id,
118                io_warfare_type,
119                io_simulation_source,
120                io_action_type,
121                io_action_phase,
122                padding1,
123                io_attacker_entity_id,
124                io_primary_target_entity_id,
125                padding2,
126                io_records,
127            })
128        } else {
129            Err(DISError::invalid_header(
130                format!(
131                    "Expected PDU type InformationOperationsAction, got {:?}",
132                    pdu_header.pdu_type
133                ),
134                None,
135            ))
136        }
137    }
138
139    fn as_any(&self) -> &dyn Any {
140        self
141    }
142
143    fn deserialize_without_header(
144        mut buffer: BytesMut,
145        pdu_header: PduHeader,
146    ) -> Result<Self, DISError>
147    where
148        Self: Sized,
149    {
150        let originating_simulation_id = EntityId::deserialize(&mut buffer);
151        let receiving_simulation_id = EntityId::deserialize(&mut buffer);
152        let request_id = buffer.get_u32();
153        let io_warfare_type = IOActionIOWarfareType::deserialize(&mut buffer);
154        let io_simulation_source = IOActionIOSimulationSource::deserialize(&mut buffer);
155        let io_action_type = IOActionIOActionType::deserialize(&mut buffer);
156        let io_action_phase = IOActionIOActionPhase::deserialize(&mut buffer);
157        let padding1 = buffer.get_u32();
158        let io_attacker_entity_id = EntityId::deserialize(&mut buffer);
159        let io_primary_target_entity_id = EntityId::deserialize(&mut buffer);
160        let padding2 = buffer.get_u16();
161        let io_records = StandardVariableSpecification::deserialize(&mut buffer);
162        Ok(InformationOperationsActionPdu {
163            pdu_header,
164            originating_simulation_id,
165            receiving_simulation_id,
166            request_id,
167            io_warfare_type,
168            io_simulation_source,
169            io_action_type,
170            io_action_phase,
171            padding1,
172            io_attacker_entity_id,
173            io_primary_target_entity_id,
174            padding2,
175            io_records,
176        })
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::InformationOperationsActionPdu;
183    use crate::common::{
184        pdu::Pdu,
185        pdu_header::{PduHeader, PduType, ProtocolFamily},
186    };
187    use bytes::BytesMut;
188
189    #[test]
190    fn create_header() {
191        let information_operations_action_pdu = InformationOperationsActionPdu::default();
192        let pdu_header = PduHeader::default(
193            PduType::InformationOperationsAction,
194            ProtocolFamily::InformationOperations,
195            32,
196        );
197
198        assert_eq!(
199            pdu_header.protocol_version,
200            information_operations_action_pdu
201                .pdu_header
202                .protocol_version
203        );
204        assert_eq!(
205            pdu_header.exercise_id,
206            information_operations_action_pdu.pdu_header.exercise_id
207        );
208        assert_eq!(
209            pdu_header.pdu_type,
210            information_operations_action_pdu.pdu_header.pdu_type
211        );
212        assert_eq!(
213            pdu_header.protocol_family,
214            information_operations_action_pdu.pdu_header.protocol_family
215        );
216        assert_eq!(
217            pdu_header.length,
218            information_operations_action_pdu.pdu_header.length
219        );
220        assert_eq!(
221            pdu_header.status_record,
222            information_operations_action_pdu.pdu_header.status_record
223        );
224    }
225
226    #[test]
227    fn deserialize_header() {
228        let mut information_operations_action_pdu = InformationOperationsActionPdu::default();
229        let mut buffer = BytesMut::new();
230        information_operations_action_pdu.serialize(&mut buffer);
231
232        let new_information_operations_action_pdu =
233            InformationOperationsActionPdu::deserialize(buffer).unwrap();
234        assert_eq!(
235            new_information_operations_action_pdu.pdu_header,
236            information_operations_action_pdu.pdu_header
237        );
238    }
239}