open_dis_rust/
entity_information.rs

1//     open-dis-rust - Rust implementation of the IEEE-1278.1-2012 Distributed Interactive Simulation
2//                     (DIS) application protocol
3//     Copyright (C) 2025 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7//! The Entity Information / Interaction protocol family
8
9#![allow(deprecated)]
10
11use crate::common::data_types::attribute_record_set::AttributeRecordSet;
12use crate::common::data_types::dead_reckoning_parameters::DeadReckoningParameters;
13use crate::common::data_types::entity_marking::EntityMarking;
14use crate::common::data_types::{
15    EntityCoordinateVector, EntityId, EntityType, EulerAngles, EventId, LinearVelocity,
16    SimulationAddress, VariableParameter, WorldCoordinate,
17};
18use crate::common::enums::{EntityCapabilities, ForceId};
19use crate::{
20    common::{
21        GenericHeader, SerializedLength,
22        enums::{DISAttributeActionCode, PduType, ProtocolFamily},
23        pdu::Pdu,
24        pdu_header::PduHeader,
25    },
26    define_pdu,
27};
28
29define_pdu! {
30    #[derive(Debug)]
31    /// Implemented according to IEEE 1278.1-2012 §7.2.2
32    pub struct EntityStatePdu {
33        header: PduHeader,
34        pdu_type: PduType::EntityState,
35        protocol_family: ProtocolFamily::EntityInformation,
36        fields: {
37            pub entity_id: EntityId,
38            pub force_id: ForceId,
39            pub number_of_articulation_parameters: u8,
40            pub entity_type: EntityType,
41            pub alternative_entity_type: EntityType,
42            pub entity_linear_velocity: LinearVelocity,
43            pub entity_location: WorldCoordinate,
44            pub entity_orientation: EulerAngles,
45            pub entity_appearance: u32,
46            pub dead_reckoning_parameters: DeadReckoningParameters,
47            pub entity_marking: EntityMarking,
48            pub entity_capabilities: EntityCapabilities,
49            pub articulation_parameter: Vec<VariableParameter>,
50        }
51    }
52}
53
54define_pdu! {
55    #[derive(Debug)]
56    /// Implemented according to IEEE 1278.1-2012 §7.2.3
57    pub struct CollisionPdu {
58        header: PduHeader,
59        pdu_type: PduType::Collision,
60        protocol_family: ProtocolFamily::EntityInformation,
61        fields: {
62            pub issuing_entity_id: EntityId,
63            pub colliding_entity_id: EntityId,
64            pub event_id: EventId,
65            pub collision_type: u8,
66            padding: u8,
67            pub velocity: LinearVelocity,
68            pub mass: f32,
69            pub location_wrt_entity: EntityCoordinateVector,
70        }
71    }
72}
73
74define_pdu! {
75    #[derive(Debug)]
76    /// Implemented according to IEEE 1278.1-2012 §7.2.4
77    pub struct CollisionElasticPdu {
78        header: PduHeader,
79        pdu_type: PduType::CollisionElastic,
80        protocol_family: ProtocolFamily::EntityInformation,
81        fields: {
82            pub issuing_entity_id: EntityId,
83            pub colliding_entity_id: EntityId,
84            pub event_id: EventId,
85            padding: u16,
86            pub contact_velocity: LinearVelocity,
87            pub mass: f32,
88            pub location_of_impact: EntityCoordinateVector,
89            pub collision_intermediate_result_xx: f32,
90            pub collision_intermediate_result_xy: f32,
91            pub collision_intermediate_result_xz: f32,
92            pub collision_intermediate_result_yy: f32,
93            pub collision_intermediate_result_yz: f32,
94            pub collision_intermediate_result_zz: f32,
95            pub unit_surface_normal: EntityCoordinateVector,
96            pub coefficient_of_restitution: f32,
97        }
98    }
99}
100
101define_pdu! {
102    #[derive(Debug)]
103    /// Implemented according to IEEE 1278.1-2012 §7.2.5
104    pub struct EntityStateUpdatePdu {
105        header: PduHeader,
106        pdu_type: PduType::EntityStateUpdate,
107        protocol_family: ProtocolFamily::EntityInformation,
108        fields: {
109            pub entity_id: EntityId,
110            padding: u8,
111            pub number_of_variable_parameters: u8,
112            pub entity_linear_velocity: LinearVelocity,
113            pub entity_location: WorldCoordinate,
114            pub entity_orientation: EulerAngles,
115            pub entity_appearance: u32,
116            pub variable_parameter_records: Vec<VariableParameter>,
117        }
118    }
119}
120
121define_pdu! {
122    #[derive(Debug)]
123    /// Implemented according to IEEE 1278.1-2012 §7.2.6
124    pub struct AttributePdu {
125        header: PduHeader,
126        pdu_type: PduType::Attribute,
127        protocol_family: ProtocolFamily::EntityInformation,
128        fields: {
129            pub originating_simulation_address: SimulationAddress,
130            padding: u32,
131            padding2: u16,
132            pub attribute_record_pdu_type: u8,
133            pub attribute_record_protocol_version: u8,
134            pub master_attribute_record_type: u32,
135            pub action_code: DISAttributeActionCode,
136            padding3: u8,
137            pub number_of_attribute_record_sets: u16,
138            pub attribute_record_sets: Vec<AttributeRecordSet>,
139        }
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146    use crate::common::{constants::BITS_PER_BYTE, pdu::Pdu};
147    use bytes::BytesMut;
148
149    mod entity_state_pdu_tests {
150        use super::*;
151
152        #[test]
153        fn cast_to_any() {
154            let pdu = EntityStatePdu::new();
155            let any_pdu = pdu.as_any();
156
157            assert!(any_pdu.is::<EntityStatePdu>());
158        }
159
160        #[test]
161        fn serialize_then_deserialize() {
162            let mut pdu = EntityStatePdu::new();
163            let mut serialize_buf = BytesMut::new();
164            let _ = pdu.serialize(&mut serialize_buf);
165
166            let mut deserialize_buf = serialize_buf.freeze();
167            let new_pdu = EntityStatePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
168            assert_eq!(new_pdu.header, pdu.header);
169        }
170
171        #[test]
172        fn check_default_pdu_length() {
173            const DEFAULT_LENGTH: u16 = 1152 / BITS_PER_BYTE;
174            let pdu = EntityStatePdu::new();
175            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
176        }
177    }
178
179    mod collision_pdu_tests {
180        use super::*;
181
182        #[test]
183        fn cast_to_any() {
184            let pdu = CollisionPdu::new();
185            let any_pdu = pdu.as_any();
186
187            assert!(any_pdu.is::<CollisionPdu>());
188        }
189
190        #[test]
191        fn serialize_then_deserialize() {
192            let mut pdu = CollisionPdu::new();
193            let mut serialize_buf = BytesMut::new();
194            let _ = pdu.serialize(&mut serialize_buf);
195
196            let mut deserialize_buf = serialize_buf.freeze();
197            let new_pdu = CollisionPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
198            assert_eq!(new_pdu.header, pdu.header);
199        }
200
201        #[test]
202        fn check_default_pdu_length() {
203            const DEFAULT_LENGTH: u16 = 480 / BITS_PER_BYTE;
204            let pdu = CollisionPdu::new();
205            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
206        }
207    }
208
209    mod collision_elastic_pdu_tests {
210        use super::*;
211
212        #[test]
213        fn cast_to_any() {
214            let pdu = CollisionElasticPdu::new();
215            let any_pdu = pdu.as_any();
216
217            assert!(any_pdu.is::<CollisionElasticPdu>());
218        }
219
220        #[test]
221        fn serialize_then_deserialize() {
222            let mut pdu = CollisionElasticPdu::new();
223            let mut serialize_buf = BytesMut::new();
224            let _ = pdu.serialize(&mut serialize_buf);
225
226            let mut deserialize_buf = serialize_buf.freeze();
227            let new_pdu =
228                CollisionElasticPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
229            assert_eq!(new_pdu.header, pdu.header);
230        }
231
232        #[test]
233        fn check_default_pdu_length() {
234            const DEFAULT_LENGTH: u16 = 800 / BITS_PER_BYTE;
235            let pdu = CollisionElasticPdu::new();
236            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
237        }
238    }
239
240    mod entity_state_update_pdu_tests {
241        use super::*;
242
243        #[test]
244        fn cast_to_any() {
245            let pdu = EntityStateUpdatePdu::new();
246            let any_pdu = pdu.as_any();
247
248            assert!(any_pdu.is::<EntityStateUpdatePdu>());
249        }
250
251        #[test]
252        fn serialize_then_deserialize() {
253            let mut pdu = EntityStateUpdatePdu::new();
254            let mut serialize_buf = BytesMut::new();
255            let _ = pdu.serialize(&mut serialize_buf);
256
257            let mut deserialize_buf = serialize_buf.freeze();
258            let new_pdu =
259                EntityStateUpdatePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
260            assert_eq!(new_pdu.header, pdu.header);
261        }
262
263        #[test]
264        fn check_default_pdu_length() {
265            const DEFAULT_LENGTH: u16 = 576 / BITS_PER_BYTE;
266            let pdu = EntityStateUpdatePdu::new();
267            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
268        }
269    }
270
271    mod attribute_pdu_tests {
272        use super::*;
273
274        #[test]
275        fn cast_to_any() {
276            let pdu = AttributePdu::new();
277            let any_pdu = pdu.as_any();
278
279            assert!(any_pdu.is::<AttributePdu>());
280        }
281
282        #[test]
283        fn serialize_then_deserialize() {
284            let mut pdu = AttributePdu::new();
285            let mut serialize_buf = BytesMut::new();
286            let _ = pdu.serialize(&mut serialize_buf);
287
288            let mut deserialize_buf = serialize_buf.freeze();
289            let new_pdu = AttributePdu::deserialize(&mut deserialize_buf).unwrap_or_default();
290            assert_eq!(new_pdu.header, pdu.header);
291        }
292
293        #[test]
294        fn check_default_pdu_length() {
295            const DEFAULT_LENGTH: u16 = 256 / BITS_PER_BYTE;
296            let pdu = AttributePdu::new();
297            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
298        }
299    }
300}