open_dis_rust/synthetic_environment/
point_object_state_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::common::{
11    dis_error::DISError,
12    entity_id::EntityId,
13    euler_angles::EulerAngles,
14    pdu::Pdu,
15    pdu_header::{PduHeader, PduType, ProtocolFamily},
16    simulation_address::SimulationAddress,
17    vector3_double::Vector3Double,
18};
19
20use super::data_types::object_type::ObjectType;
21
22#[derive(Clone, Debug)]
23/// Implemented according to IEEE 1278.1-2012 ยง7.10.4
24pub struct PointObjectStatePdu {
25    pub pdu_header: PduHeader,
26    pub object_id: EntityId,
27    pub referenced_object_id: EntityId,
28    pub update_number: u16,
29    pub force_id: u8,
30    pub modifications: u8,
31    pub object_type: ObjectType,
32    pub object_location: Vector3Double,
33    pub object_orientation: EulerAngles,
34    pub object_appearance: f64,
35    pub requester_id: SimulationAddress,
36    pub receiving_id: SimulationAddress,
37    pub pad2: u32,
38}
39
40impl Default for PointObjectStatePdu {
41    /// Creates a default Point Object State PDU with arbitrary environmental process ID
42    ///
43    /// # Examples
44    ///
45    /// Initializing a Point Object State PDU:
46    /// ```
47    /// use open_dis_rust::synthetic_environment::point_object_state_pdu::PointObjectStatePdu;
48    /// let point_object_state_pdu = PointObjectStatePdu::default();
49    /// ```
50    ///
51    fn default() -> Self {
52        PointObjectStatePdu {
53            pdu_header: PduHeader::default(
54                PduType::PointObjectState,
55                ProtocolFamily::SyntheticEnvironment,
56                56,
57            ),
58            object_id: EntityId::default(1),
59            referenced_object_id: EntityId::default(2),
60            update_number: 0,
61            force_id: 0,
62            modifications: 0,
63            object_type: ObjectType::default(),
64            object_location: Vector3Double::default(),
65            object_orientation: EulerAngles::default(),
66            object_appearance: 0.0,
67            requester_id: SimulationAddress::default(),
68            receiving_id: SimulationAddress::default(),
69            pad2: 0,
70        }
71    }
72}
73
74impl Pdu for PointObjectStatePdu {
75    fn serialize(&mut self, buf: &mut BytesMut) {
76        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
77            .expect("The length of the PDU should fit in a u16.");
78        self.pdu_header.serialize(buf);
79        self.object_id.serialize(buf);
80        self.referenced_object_id.serialize(buf);
81        buf.put_u16(self.update_number);
82        buf.put_u8(self.force_id);
83        buf.put_u8(self.modifications);
84        self.object_type.serialize(buf);
85        self.object_location.serialize(buf);
86        self.object_orientation.serialize(buf);
87        buf.put_f64(self.object_appearance);
88        self.requester_id.serialize(buf);
89        self.receiving_id.serialize(buf);
90        buf.put_u32(self.pad2);
91    }
92
93    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
94    where
95        Self: Sized,
96    {
97        let pdu_header = PduHeader::deserialize(&mut buffer);
98        if pdu_header.pdu_type == PduType::PointObjectState {
99            let object_id = EntityId::deserialize(&mut buffer);
100            let referenced_object_id = EntityId::deserialize(&mut buffer);
101            let update_number = buffer.get_u16();
102            let force_id = buffer.get_u8();
103            let modifications = buffer.get_u8();
104            let object_type = ObjectType::deserialize(&mut buffer);
105            let object_location = Vector3Double::deserialize(&mut buffer);
106            let object_orientation = EulerAngles::deserialize(&mut buffer);
107            let object_appearance = buffer.get_f64();
108            let requester_id = SimulationAddress::deserialize(&mut buffer);
109            let receiving_id = SimulationAddress::deserialize(&mut buffer);
110            let pad2 = buffer.get_u32();
111            Ok(PointObjectStatePdu {
112                pdu_header,
113                object_id,
114                referenced_object_id,
115                update_number,
116                force_id,
117                modifications,
118                object_type,
119                object_location,
120                object_orientation,
121                object_appearance,
122                requester_id,
123                receiving_id,
124                pad2,
125            })
126        } else {
127            Err(DISError::invalid_header(
128                format!(
129                    "Expected PDU type PointObjectState, got {:?}",
130                    pdu_header.pdu_type
131                ),
132                None,
133            ))
134        }
135    }
136
137    fn as_any(&self) -> &dyn Any {
138        self
139    }
140
141    fn deserialize_without_header(
142        mut buffer: BytesMut,
143        pdu_header: PduHeader,
144    ) -> Result<Self, DISError>
145    where
146        Self: Sized,
147    {
148        let object_id = EntityId::deserialize(&mut buffer);
149        let referenced_object_id = EntityId::deserialize(&mut buffer);
150        let update_number = buffer.get_u16();
151        let force_id = buffer.get_u8();
152        let modifications = buffer.get_u8();
153        let object_type = ObjectType::deserialize(&mut buffer);
154        let object_location = Vector3Double::deserialize(&mut buffer);
155        let object_orientation = EulerAngles::deserialize(&mut buffer);
156        let object_appearance = buffer.get_f64();
157        let requester_id = SimulationAddress::deserialize(&mut buffer);
158        let receiving_id = SimulationAddress::deserialize(&mut buffer);
159        let pad2 = buffer.get_u32();
160        Ok(PointObjectStatePdu {
161            pdu_header,
162            object_id,
163            referenced_object_id,
164            update_number,
165            force_id,
166            modifications,
167            object_type,
168            object_location,
169            object_orientation,
170            object_appearance,
171            requester_id,
172            receiving_id,
173            pad2,
174        })
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use super::PointObjectStatePdu;
181    use crate::common::{
182        pdu::Pdu,
183        pdu_header::{PduHeader, PduType, ProtocolFamily},
184    };
185    use bytes::BytesMut;
186
187    #[test]
188    fn create_header() {
189        let point_object_state_pdu = PointObjectStatePdu::default();
190        let pdu_header = PduHeader::default(
191            PduType::PointObjectState,
192            ProtocolFamily::SyntheticEnvironment,
193            448 / 8,
194        );
195
196        assert_eq!(
197            pdu_header.protocol_version,
198            point_object_state_pdu.pdu_header.protocol_version
199        );
200        assert_eq!(
201            pdu_header.exercise_id,
202            point_object_state_pdu.pdu_header.exercise_id
203        );
204        assert_eq!(
205            pdu_header.pdu_type,
206            point_object_state_pdu.pdu_header.pdu_type
207        );
208        assert_eq!(
209            pdu_header.protocol_family,
210            point_object_state_pdu.pdu_header.protocol_family
211        );
212        assert_eq!(pdu_header.length, point_object_state_pdu.pdu_header.length);
213        assert_eq!(
214            pdu_header.status_record,
215            point_object_state_pdu.pdu_header.status_record
216        );
217    }
218
219    #[test]
220    fn deserialize_header() {
221        let mut point_object_state_pdu = PointObjectStatePdu::default();
222        let mut buffer = BytesMut::new();
223        point_object_state_pdu.serialize(&mut buffer);
224
225        let new_point_object_state_pdu = PointObjectStatePdu::deserialize(buffer).unwrap();
226        assert_eq!(
227            new_point_object_state_pdu.pdu_header,
228            point_object_state_pdu.pdu_header
229        );
230    }
231}