open_dis_rust/radio_communications/
intercom_control_pdu.rs

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