open_dis_rust/entity_information/
entity_state_pdu.rs1use bytes::{Buf, BufMut, BytesMut};
8use std::any::Any;
9
10use crate::common::{
11 dis_error::DISError,
12 entity_id::EntityId,
13 entity_type::EntityType,
14 enums::{Country, EntityCapabilities, EntityKind, ForceId},
15 euler_angles::EulerAngles,
16 linear_velocity::LinearVelocity,
17 pdu::Pdu,
18 pdu_header::{PduHeader, PduType, ProtocolFamily},
19 world_coordinate::WorldCoordinate,
20};
21
22use super::data_types::{
23 dead_reckoning_parameters::DeadReckoningParameters, entity_marking::EntityMarking,
24};
25
26#[derive(Clone, Debug)]
27pub struct EntityStatePdu {
29 pub pdu_header: PduHeader,
30 pub entity_id: EntityId,
31 pub force_id: ForceId,
32 pub number_of_articulation_parameters: u8,
33 pub entity_type: EntityType,
34 pub alternative_entity_type: EntityType,
35 pub entity_linear_velocity: LinearVelocity,
36 pub entity_location: WorldCoordinate,
37 pub entity_orientation: EulerAngles,
38 pub entity_appearance: u32,
39 pub dead_reckoning_parameters: DeadReckoningParameters,
40 pub entity_marking: EntityMarking,
41 pub entity_capabilities: EntityCapabilities,
42 pub articulation_parameter: f32,
43}
44
45impl Default for EntityStatePdu {
46 fn default() -> Self {
47 EntityStatePdu {
48 pdu_header: PduHeader::default(
49 PduType::EntityState,
50 ProtocolFamily::EntityInformation,
51 864 / 8,
52 ),
53 entity_id: EntityId::default(2),
54 force_id: ForceId::default(),
55 number_of_articulation_parameters: 0,
56 entity_type: EntityType {
57 kind: EntityKind::default(),
58 domain: 1,
59 country: Country::default(),
60 category: 3,
61 subcategory: 0,
62 specific: 0,
63 extra: 0,
64 },
65 alternative_entity_type: EntityType {
66 kind: EntityKind::default(),
67 domain: 1,
68 country: Country::default(),
69 category: 0,
70 subcategory: 0,
71 specific: 0,
72 extra: 0,
73 },
74 entity_linear_velocity: LinearVelocity::new(0.0, 0.0, 0.0),
75 entity_location: WorldCoordinate::new(0.0, 0.0, 0.0),
76 entity_orientation: EulerAngles::new(0.0, 0.0, 0.0),
77 entity_appearance: 0,
78 dead_reckoning_parameters: DeadReckoningParameters::default(),
79 entity_marking: EntityMarking::default(String::new()),
80 entity_capabilities: EntityCapabilities::default(),
81 articulation_parameter: 0.0,
82 }
83 }
84}
85
86impl Pdu for EntityStatePdu {
87 fn serialize(&mut self, buf: &mut BytesMut) {
88 self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
89 .expect("The length of the PDU should fit in a u16.");
90 self.pdu_header.serialize(buf);
91 self.entity_id.serialize(buf);
92 buf.put_u8(self.force_id as u8);
93 buf.put_u8(self.number_of_articulation_parameters);
94 self.entity_type.serialize(buf);
95 self.alternative_entity_type.serialize(buf);
96 self.entity_linear_velocity.serialize(buf);
97 self.entity_location.serialize(buf);
98 self.entity_orientation.serialize(buf);
99 buf.put_u32(self.entity_appearance);
100 self.dead_reckoning_parameters.serialize(buf);
101 self.entity_marking.serialize(buf);
102 buf.put_u8(self.entity_capabilities as u8);
103 }
104
105 fn deserialize(mut buffer: BytesMut) -> Result<EntityStatePdu, DISError> {
106 let pdu_header = PduHeader::deserialize(&mut buffer);
107 if pdu_header.pdu_type == PduType::EntityState {
108 let entity_id = EntityId::deserialize(&mut buffer);
109 let force_id = ForceId::deserialize(&mut buffer);
110 let articulation_params = &buffer.get_u8();
111 let entity_type = EntityType::deserialize(&mut buffer);
112 let alt_entity_type = EntityType::deserialize(&mut buffer);
113 let linear_velocity = LinearVelocity::deserialize(&mut buffer);
114 let world_coordinate = WorldCoordinate::deserialize(&mut buffer);
115 let orientation = EulerAngles::deserialize(&mut buffer);
116 let appearance = buffer.get_u32();
117 let dead_reckoning = DeadReckoningParameters::deserialize(&mut buffer);
118 let entity_marking = EntityMarking::deserialize(&mut buffer);
119 let entity_capabilities = EntityCapabilities::deserialize(&mut buffer);
120
121 Ok(EntityStatePdu {
122 pdu_header,
123 entity_id,
124 force_id,
125 number_of_articulation_parameters: *articulation_params,
126 entity_type,
127 alternative_entity_type: alt_entity_type,
128 entity_linear_velocity: linear_velocity,
129 entity_location: world_coordinate,
130 entity_orientation: orientation,
131 entity_appearance: appearance,
132 dead_reckoning_parameters: dead_reckoning,
133 entity_marking,
134 entity_capabilities,
135 articulation_parameter: 0.0,
136 })
137 } else {
138 Err(DISError::invalid_header(
139 format!(
140 "Expected PDU type EntityState, 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 force_id = ForceId::deserialize(&mut buffer);
161 let articulation_params = &buffer.get_u8();
162 let entity_type = EntityType::deserialize(&mut buffer);
163 let alt_entity_type = EntityType::deserialize(&mut buffer);
164 let linear_velocity = LinearVelocity::deserialize(&mut buffer);
165 let world_coordinate = WorldCoordinate::deserialize(&mut buffer);
166 let orientation = EulerAngles::deserialize(&mut buffer);
167 let appearance = buffer.get_u32();
168 let dead_reckoning_parameters = DeadReckoningParameters::deserialize(&mut buffer);
169 let entity_marking = EntityMarking::deserialize(&mut buffer);
170 let entity_capabilities = EntityCapabilities::deserialize(&mut buffer);
171
172 Ok(EntityStatePdu {
173 pdu_header,
174 entity_id,
175 force_id,
176 number_of_articulation_parameters: *articulation_params,
177 entity_type,
178 alternative_entity_type: alt_entity_type,
179 entity_linear_velocity: linear_velocity,
180 entity_location: world_coordinate,
181 entity_orientation: orientation,
182 entity_appearance: appearance,
183 dead_reckoning_parameters,
184 entity_marking,
185 entity_capabilities,
186 articulation_parameter: 0.0,
187 })
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::EntityStatePdu;
194 use crate::common::{
195 pdu::Pdu,
196 pdu_header::{PduHeader, PduType, ProtocolFamily},
197 };
198 use bytes::BytesMut;
199
200 #[test]
201 fn create_header() {
202 let entity_state_pdu = EntityStatePdu::default();
203 let header = PduHeader::default(
204 PduType::EntityState,
205 ProtocolFamily::EntityInformation,
206 864 / 8,
207 );
208 assert_eq!(
209 header.protocol_version,
210 entity_state_pdu.pdu_header.protocol_version
211 );
212 assert_eq!(header.exercise_id, entity_state_pdu.pdu_header.exercise_id);
213 assert_eq!(header.pdu_type, entity_state_pdu.pdu_header.pdu_type);
214 assert_eq!(
215 header.protocol_family,
216 entity_state_pdu.pdu_header.protocol_family
217 );
218 assert_eq!(header.length, entity_state_pdu.pdu_header.length);
219 assert_eq!(
220 header.status_record,
221 entity_state_pdu.pdu_header.status_record
222 );
223 }
224
225 #[test]
226 fn deserialize_header() {
227 let mut entity_state_pdu = EntityStatePdu::default();
228 let mut buffer = BytesMut::new();
229 entity_state_pdu.serialize(&mut buffer);
230
231 let new_entity_state_pdu = EntityStatePdu::deserialize(buffer).unwrap();
232 assert_eq!(new_entity_state_pdu.pdu_header, entity_state_pdu.pdu_header);
233 }
234}