open_dis_rust/distributed_emissions/
designator_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
7#![allow(deprecated)]
8
9use bytes::{Buf, BufMut, BytesMut};
10use std::any::Any;
11
12use crate::common::{
13    dis_error::DISError,
14    entity_id::EntityId,
15    enums::{DeadReckoningAlgorithm, DesignatorCode, DesignatorSystemName},
16    pdu::Pdu,
17    pdu_header::{PduHeader, PduType, ProtocolFamily},
18    vector3_double::Vector3Double,
19    vector3_float::Vector3Float,
20};
21
22#[derive(Copy, Clone, Debug)]
23/// Implemented according to IEEE 1278.1-2012 ยง7.6.3
24pub struct DesignatorPdu {
25    pub pdu_header: PduHeader,
26    pub designating_entity_id: EntityId,
27    pub code_name: DesignatorSystemName,
28    pub designated_entity_id: EntityId,
29    pub designator_code: DesignatorCode,
30    pub designator_power: f32,
31    pub designator_wavelength: f32,
32    pub designator_spot_wrt_designated: Vector3Float,
33    pub designator_spot_location: Vector3Double,
34    pub dead_reckoning_algorithm: DeadReckoningAlgorithm,
35    pub padding1: u8,
36    pub padding2: u16,
37    pub entity_linear_acceleration: Vector3Float,
38}
39
40impl Default for DesignatorPdu {
41    /// Creates a default-initialized Designator PDU
42    ///
43    /// # Examples
44    ///
45    /// Initializing a Designator PDU:
46    /// ```
47    /// use open_dis_rust::distributed_emissions::designator_pdu::DesignatorPdu;
48    /// let mut designator_pdu = DesignatorPdu::default();
49    /// ```
50    ///
51    fn default() -> Self {
52        DesignatorPdu {
53            pdu_header: PduHeader::default(
54                PduType::Designator,
55                ProtocolFamily::DistributedEmissionRegeneration,
56                88,
57            ),
58            designating_entity_id: EntityId::default(1),
59            code_name: DesignatorSystemName::default(),
60            designated_entity_id: EntityId::default(2),
61            designator_code: DesignatorCode::default(),
62            designator_power: 0.0,
63            designator_wavelength: 0.0,
64            designator_spot_wrt_designated: Vector3Float::new(0.0, 0.0, 0.0),
65            designator_spot_location: Vector3Double::new(0.0, 0.0, 0.0),
66            dead_reckoning_algorithm: DeadReckoningAlgorithm::default(),
67            padding1: 0,
68            padding2: 0,
69            entity_linear_acceleration: Vector3Float::new(0.0, 0.0, 0.0),
70        }
71    }
72}
73
74impl Pdu for DesignatorPdu {
75    /// Serialize contents of `DesignatorPdu` into `BytesMut` buffer
76    fn serialize(&mut self, buf: &mut BytesMut) {
77        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
78            .expect("The length of the PDU should fit in a u16.");
79        self.pdu_header.serialize(buf);
80        self.designating_entity_id.serialize(buf);
81        buf.put_u16(self.designator_code as u16);
82        self.designated_entity_id.serialize(buf);
83        buf.put_u16(self.designator_code as u16);
84        buf.put_f32(self.designator_power);
85        buf.put_f32(self.designator_wavelength);
86        self.designator_spot_wrt_designated.serialize(buf);
87        self.designator_spot_location.serialize(buf);
88        buf.put_u8(self.dead_reckoning_algorithm as u8);
89        buf.put_u8(self.padding1);
90        buf.put_u16(self.padding2);
91        self.entity_linear_acceleration.serialize(buf);
92    }
93
94    /// Deserialize bytes from `BytesMut` buffer and interpret as `DesignatorPdu`
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::Designator {
101            let designating_entity_id = EntityId::deserialize(&mut buffer);
102            let code_name = DesignatorSystemName::deserialize(&mut buffer);
103            let designated_entity_id = EntityId::deserialize(&mut buffer);
104            let designator_code = DesignatorCode::deserialize(&mut buffer);
105            let designator_power = buffer.get_f32();
106            let designator_wavelength = buffer.get_f32();
107            let designator_spot_wrt_designated = Vector3Float::deserialize(&mut buffer);
108            let designator_spot_location = Vector3Double::deserialize(&mut buffer);
109            let dead_reckoning_algorithm = DeadReckoningAlgorithm::deserialize(&mut buffer);
110            let padding1 = buffer.get_u8();
111            let padding2 = buffer.get_u16();
112            let entity_linear_acceleration = Vector3Float::deserialize(&mut buffer);
113
114            Ok(DesignatorPdu {
115                pdu_header,
116                designating_entity_id,
117                code_name,
118                designated_entity_id,
119                designator_code,
120                designator_power,
121                designator_wavelength,
122                designator_spot_wrt_designated,
123                designator_spot_location,
124                dead_reckoning_algorithm,
125                padding1,
126                padding2,
127                entity_linear_acceleration,
128            })
129        } else {
130            Err(DISError::invalid_header(
131                format!(
132                    "Expected PDU type Designator, got {:?}",
133                    pdu_header.pdu_type
134                ),
135                None,
136            ))
137        }
138    }
139
140    /// Treat `DesignatorPdu` as Any type
141    fn as_any(&self) -> &dyn Any {
142        self
143    }
144
145    /// Deserialize bytes from `BytesMut` buffer, but assume PDU header exists already
146    fn deserialize_without_header(
147        mut buffer: BytesMut,
148        pdu_header: PduHeader,
149    ) -> Result<Self, DISError>
150    where
151        Self: Sized,
152    {
153        let designating_entity_id = EntityId::deserialize(&mut buffer);
154        let code_name = DesignatorSystemName::deserialize(&mut buffer);
155        let designated_entity_id = EntityId::deserialize(&mut buffer);
156        let designator_code = DesignatorCode::deserialize(&mut buffer);
157        let designator_power = buffer.get_f32();
158        let designator_wavelength = buffer.get_f32();
159        let designator_spot_wrt_designated = Vector3Float::deserialize(&mut buffer);
160        let designator_spot_location = Vector3Double::deserialize(&mut buffer);
161        let dead_reckoning_algorithm = DeadReckoningAlgorithm::deserialize(&mut buffer);
162        let padding1 = buffer.get_u8();
163        let padding2 = buffer.get_u16();
164        let entity_linear_acceleration = Vector3Float::deserialize(&mut buffer);
165
166        Ok(DesignatorPdu {
167            pdu_header,
168            designating_entity_id,
169            code_name,
170            designated_entity_id,
171            designator_code,
172            designator_power,
173            designator_wavelength,
174            designator_spot_wrt_designated,
175            designator_spot_location,
176            dead_reckoning_algorithm,
177            padding1,
178            padding2,
179            entity_linear_acceleration,
180        })
181    }
182}
183
184#[cfg(test)]
185mod tests {
186    use super::DesignatorPdu;
187    use crate::common::{
188        pdu::Pdu,
189        pdu_header::{PduHeader, PduType, ProtocolFamily},
190    };
191    use bytes::BytesMut;
192
193    #[test]
194    fn create_header() {
195        let designator_pdu = DesignatorPdu::default();
196        let pdu_header = PduHeader::default(
197            PduType::Designator,
198            ProtocolFamily::DistributedEmissionRegeneration,
199            88,
200        );
201
202        assert_eq!(
203            pdu_header.protocol_version,
204            designator_pdu.pdu_header.protocol_version
205        );
206        assert_eq!(
207            pdu_header.exercise_id,
208            designator_pdu.pdu_header.exercise_id
209        );
210        assert_eq!(pdu_header.pdu_type, designator_pdu.pdu_header.pdu_type);
211        assert_eq!(
212            pdu_header.protocol_family,
213            designator_pdu.pdu_header.protocol_family
214        );
215        assert_eq!(pdu_header.length, designator_pdu.pdu_header.length);
216        assert_eq!(
217            pdu_header.status_record,
218            designator_pdu.pdu_header.status_record
219        );
220    }
221
222    #[test]
223    fn cast_to_any() {
224        let designator_pdu = DesignatorPdu::default();
225        let any_pdu = designator_pdu.as_any();
226
227        assert!(any_pdu.is::<DesignatorPdu>());
228    }
229
230    #[test]
231    fn deserialize_header() {
232        let mut designator_pdu = DesignatorPdu::default();
233        let mut buffer = BytesMut::new();
234        designator_pdu.serialize(&mut buffer);
235
236        let new_designator_pdu = DesignatorPdu::deserialize(buffer).unwrap();
237        assert_eq!(new_designator_pdu.pdu_header, designator_pdu.pdu_header);
238    }
239}