1use crate::common::model::{
2 length_padded_to_num, ArticulatedPart, AttachedPart, BeamData, ClockTime, DescriptorRecord,
3 EntityAssociationParameter, EntityId, EntityTypeParameter, EventId, FixedDatum, Location,
4 MunitionDescriptor, Orientation, SeparationParameter, SimulationAddress, VariableDatum,
5 VariableParameter, VectorF32,
6};
7use crate::common::model::{Pdu, PduBody, PduHeader};
8use crate::common::{Serialize, SerializePdu, SupportedVersion};
9use crate::constants::{EIGHT_OCTETS, FOUR_OCTETS, ONE_BYTE_IN_BITS, PDU_HEADER_LEN_BYTES};
10use crate::enumerations::{ProtocolVersion, VariableParameterRecordType};
11use crate::model::{RecordSet, RecordSpecification, SupplyQuantity};
12use crate::DisError;
13use bytes::{BufMut, BytesMut};
14
15impl Serialize for PduHeader {
16 fn serialize(&self, buf: &mut BytesMut) -> u16 {
17 buf.put_u8(self.protocol_version.into());
18 buf.put_u8(self.exercise_id);
19 buf.put_u8(self.pdu_type.into());
20 buf.put_u8(self.protocol_family.into());
21 buf.put_u32(self.time_stamp);
22 buf.put_u16(self.pdu_length);
23 match self.protocol_version {
24 ProtocolVersion::IEEE1278_12012 => {
25 if let Some(status) = self.pdu_status {
26 buf.put_u8(crate::v7::writer::serialize_pdu_status(
27 &status,
28 &self.pdu_type,
29 ));
30 buf.put_u8(0u8);
31 } else {
32 buf.put_u16(0u16);
33 }
34 }
35 _ => buf.put_u16(0u16),
36 }
37
38 PDU_HEADER_LEN_BYTES
39 }
40}
41
42impl Pdu {
43 pub fn serialize(&self, buf: &mut BytesMut) -> Result<u16, DisError> {
50 if self.pdu_length() as usize > buf.capacity() {
51 return Err(DisError::InsufficientBufferSize(
52 self.pdu_length(),
53 buf.capacity(),
54 ));
55 }
56 let header_size = self.header.serialize(buf);
57 let version: SupportedVersion = self.header.protocol_version.into();
58 let body_size = match &self.body {
59 PduBody::Other(body) => body.serialize_pdu(version, buf),
60 PduBody::EntityState(body) => body.serialize_pdu(version, buf),
61 PduBody::Fire(body) => body.serialize_pdu(version, buf),
62 PduBody::Detonation(body) => body.serialize_pdu(version, buf),
63 PduBody::Collision(body) => body.serialize_pdu(version, buf),
64 PduBody::ServiceRequest(body) => body.serialize_pdu(version, buf),
65 PduBody::ResupplyOffer(body) => body.serialize_pdu(version, buf),
66 PduBody::ResupplyReceived(body) => body.serialize_pdu(version, buf),
67 PduBody::ResupplyCancel(body) => body.serialize_pdu(version, buf),
68 PduBody::RepairComplete(body) => body.serialize_pdu(version, buf),
69 PduBody::RepairResponse(body) => body.serialize_pdu(version, buf),
70 PduBody::CreateEntity(body) => body.serialize_pdu(version, buf),
71 PduBody::RemoveEntity(body) => body.serialize_pdu(version, buf),
72 PduBody::StartResume(body) => body.serialize_pdu(version, buf),
73 PduBody::StopFreeze(body) => body.serialize_pdu(version, buf),
74 PduBody::Acknowledge(body) => body.serialize_pdu(version, buf),
75 PduBody::ActionRequest(body) => body.serialize_pdu(version, buf),
76 PduBody::ActionResponse(body) => body.serialize_pdu(version, buf),
77 PduBody::DataQuery(body) => body.serialize_pdu(version, buf),
78 PduBody::SetData(body) => body.serialize_pdu(version, buf),
79 PduBody::Data(body) => body.serialize_pdu(version, buf),
80 PduBody::EventReport(body) => body.serialize_pdu(version, buf),
81 PduBody::Comment(body) => body.serialize_pdu(version, buf),
82 PduBody::ElectromagneticEmission(body) => body.serialize_pdu(version, buf),
83 PduBody::Designator(body) => body.serialize_pdu(version, buf),
84 PduBody::Transmitter(body) => body.serialize_pdu(version, buf),
85 PduBody::Signal(body) => body.serialize_pdu(version, buf),
86 PduBody::Receiver(body) => body.serialize_pdu(version, buf),
87 PduBody::IFF(body) => body.serialize_pdu(version, buf),
88 PduBody::UnderwaterAcoustic(body) => body.serialize_pdu(version, buf),
89 PduBody::SupplementalEmissionEntityState(body) => body.serialize_pdu(version, buf),
90 PduBody::AggregateState(body) => body.serialize_pdu(version, buf),
93 PduBody::IsGroupOf(body) => body.serialize_pdu(version, buf),
94 PduBody::TransferOwnership(body) => body.serialize_pdu(version, buf),
95 PduBody::IsPartOf(body) => body.serialize_pdu(version, buf),
96 PduBody::CreateEntityR(body) => body.serialize_pdu(version, buf),
111 PduBody::RemoveEntityR(body) => body.serialize_pdu(version, buf),
112 PduBody::StartResumeR(body) => body.serialize_pdu(version, buf),
113 PduBody::StopFreezeR(body) => body.serialize_pdu(version, buf),
114 PduBody::AcknowledgeR(body) => body.serialize_pdu(version, buf),
115 PduBody::ActionRequestR(body) => body.serialize_pdu(version, buf),
116 PduBody::ActionResponseR(body) => body.serialize_pdu(version, buf),
117 PduBody::DataQueryR(body) => body.serialize_pdu(version, buf),
118 PduBody::SetDataR(body) => body.serialize_pdu(version, buf),
119 PduBody::DataR(body) => body.serialize_pdu(version, buf),
120 PduBody::EventReportR(body) => body.serialize_pdu(version, buf),
121 PduBody::CommentR(body) => body.serialize_pdu(version, buf),
122 PduBody::RecordR(body) => body.serialize_pdu(version, buf),
123 PduBody::SetRecordR(body) => body.serialize_pdu(version, buf),
124 PduBody::RecordQueryR(body) => body.serialize_pdu(version, buf),
125 PduBody::CollisionElastic(body) => body.serialize_pdu(version, buf),
126 PduBody::EntityStateUpdate(body) => body.serialize_pdu(version, buf),
127 PduBody::Attribute(body) => body.serialize_pdu(version, buf),
132 _ => 0,
133 };
134
135 Ok(header_size + body_size)
136 }
137}
138
139impl Serialize for EntityId {
140 fn serialize(&self, buf: &mut BytesMut) -> u16 {
141 let num_bytes = self.simulation_address.serialize(buf);
142 buf.put_u16(self.entity_id);
143 num_bytes + 2
144 }
145}
146
147impl Serialize for SimulationAddress {
148 fn serialize(&self, buf: &mut BytesMut) -> u16 {
149 buf.put_u16(self.site_id);
150 buf.put_u16(self.application_id);
151 4
152 }
153}
154
155impl Serialize for EventId {
156 fn serialize(&self, buf: &mut BytesMut) -> u16 {
157 let num_bytes = self.simulation_address.serialize(buf);
158 buf.put_u16(self.event_id);
159 num_bytes + 2
160 }
161}
162
163impl Serialize for VectorF32 {
164 fn serialize(&self, buf: &mut BytesMut) -> u16 {
165 buf.put_f32(self.first_vector_component);
166 buf.put_f32(self.second_vector_component);
167 buf.put_f32(self.third_vector_component);
168 12
169 }
170}
171
172impl Serialize for Location {
173 fn serialize(&self, buf: &mut BytesMut) -> u16 {
174 buf.put_f64(self.x_coordinate);
175 buf.put_f64(self.y_coordinate);
176 buf.put_f64(self.z_coordinate);
177 24
178 }
179}
180
181impl Serialize for Orientation {
182 fn serialize(&self, buf: &mut BytesMut) -> u16 {
183 buf.put_f32(self.psi);
184 buf.put_f32(self.theta);
185 buf.put_f32(self.phi);
186 12
187 }
188}
189
190impl Serialize for DescriptorRecord {
191 fn serialize(&self, buf: &mut BytesMut) -> u16 {
192 match self {
193 DescriptorRecord::Munition {
194 entity_type,
195 munition,
196 } => {
197 let entity_bytes = entity_type.serialize(buf);
198 let munition_bytes = munition.serialize(buf);
199 entity_bytes + munition_bytes
200 }
201 DescriptorRecord::Expendable { entity_type } => {
202 let entity_bytes = entity_type.serialize(buf);
203 buf.put_u64(0u64);
204 entity_bytes + 8
205 }
206 DescriptorRecord::Explosion {
207 entity_type,
208 explosive_material,
209 explosive_force,
210 } => {
211 let entity_bytes = entity_type.serialize(buf);
212 buf.put_u16((*explosive_material).into());
213 buf.put_u16(0u16);
214 buf.put_f32(*explosive_force);
215 entity_bytes + 8
216 }
217 }
218 }
219}
220
221impl Serialize for MunitionDescriptor {
222 fn serialize(&self, buf: &mut BytesMut) -> u16 {
223 buf.put_u16(self.warhead.into());
224 buf.put_u16(self.fuse.into());
225 buf.put_u16(self.quantity);
226 buf.put_u16(self.rate);
227 8
228 }
229}
230
231impl Serialize for ClockTime {
232 fn serialize(&self, buf: &mut BytesMut) -> u16 {
233 buf.put_i32(self.hour);
234 buf.put_u32(self.time_past_hour);
235 8
236 }
237}
238
239impl Serialize for FixedDatum {
240 fn serialize(&self, buf: &mut BytesMut) -> u16 {
241 buf.put_u32(self.datum_id.into());
242 buf.put_u32(self.datum_value);
243
244 8
245 }
246}
247
248impl Serialize for VariableDatum {
249 #[allow(clippy::cast_possible_truncation)]
250 fn serialize(&self, buf: &mut BytesMut) -> u16 {
251 const SIXTY_FOUR_BITS: usize = 64;
252 let data_length_bits: usize = self.datum_value.len() * 8;
253 let padded_record_bits = length_padded_to_num(data_length_bits, SIXTY_FOUR_BITS);
254 let record_length_bits = padded_record_bits.record_length as u16;
255 let record_length_bytes = record_length_bits / 8;
256 let padding_length_bytes = padded_record_bits.padding_length * 8;
257
258 buf.put_u32(self.datum_id.into());
259 buf.put_u32(data_length_bits as u32);
260 buf.put_slice(self.datum_value.as_slice());
261 buf.put_bytes(0, padding_length_bytes);
262
263 8 + (record_length_bytes)
264 }
265}
266
267impl Serialize for VariableParameter {
268 fn serialize(&self, buf: &mut BytesMut) -> u16 {
269 match self {
270 VariableParameter::Articulated(inner) => {
271 buf.put_u8(VariableParameterRecordType::ArticulatedPart.into());
272 1 + inner.serialize(buf)
273 }
274 VariableParameter::Attached(inner) => {
275 buf.put_u8(VariableParameterRecordType::AttachedPart.into());
276 1 + inner.serialize(buf)
277 }
278 VariableParameter::Separation(inner) => {
279 buf.put_u8(VariableParameterRecordType::Separation.into());
280 1 + inner.serialize(buf)
281 }
282 VariableParameter::EntityType(inner) => {
283 buf.put_u8(VariableParameterRecordType::EntityType.into());
284 1 + inner.serialize(buf)
285 }
286 VariableParameter::EntityAssociation(inner) => {
287 buf.put_u8(VariableParameterRecordType::EntityAssociation.into());
288 1 + inner.serialize(buf)
289 }
290 VariableParameter::Unspecified(parameter_type, value) => {
291 buf.put_u8(*parameter_type);
292 buf.put(&value[..]);
293 16
294 }
295 }
296 }
297}
298
299impl Serialize for ArticulatedPart {
300 fn serialize(&self, buf: &mut BytesMut) -> u16 {
301 buf.put_u8(self.change_indicator.into());
302 buf.put_u16(self.attachment_id);
303 let type_class: u32 = self.type_class.into();
304 let type_metric: u32 = self.type_metric.into();
305 buf.put_u32(type_class + type_metric);
306 buf.put_f32(self.parameter_value);
307 buf.put_u32(0u32);
308
309 15
310 }
311}
312
313impl Serialize for AttachedPart {
314 fn serialize(&self, buf: &mut BytesMut) -> u16 {
315 buf.put_u8(self.detached_indicator.into());
316 buf.put_u16(self.attachment_id);
317 buf.put_u32(self.parameter_type.into());
318 self.attached_part_type.serialize(buf);
319
320 15
321 }
322}
323
324impl Serialize for SeparationParameter {
325 fn serialize(&self, buf: &mut BytesMut) -> u16 {
326 buf.put_u8(self.reason.into());
327 buf.put_u8(self.pre_entity_indicator.into());
328 buf.put_u8(0u8);
329 self.parent_entity_id.serialize(buf);
330 buf.put_u16(0u16);
331 buf.put_u16(self.station_name.into());
332 buf.put_u16(self.station_number);
333
334 15
335 }
336}
337
338impl Serialize for EntityTypeParameter {
339 fn serialize(&self, buf: &mut BytesMut) -> u16 {
340 buf.put_u8(self.change_indicator.into());
341 self.entity_type.serialize(buf);
342 buf.put_u16(0u16);
343 buf.put_u32(0u32);
344
345 15
346 }
347}
348
349impl Serialize for EntityAssociationParameter {
350 fn serialize(&self, buf: &mut BytesMut) -> u16 {
351 buf.put_u8(self.change_indicator.into());
352 buf.put_u8(self.association_status.into());
353 buf.put_u8(self.association_type.into());
354 self.entity_id.serialize(buf);
355 buf.put_u16(self.own_station_location.into());
356 buf.put_u8(self.physical_connection_type.into());
357 buf.put_u8(self.group_member_type.into());
358 buf.put_u16(self.group_number);
359
360 15
361 }
362}
363
364impl Serialize for BeamData {
365 fn serialize(&self, buf: &mut BytesMut) -> u16 {
366 buf.put_f32(self.azimuth_center);
367 buf.put_f32(self.azimuth_sweep);
368 buf.put_f32(self.elevation_center);
369 buf.put_f32(self.elevation_sweep);
370 buf.put_f32(self.sweep_sync);
371
372 20
373 }
374}
375
376impl Serialize for SupplyQuantity {
377 fn serialize(&self, buf: &mut BytesMut) -> u16 {
378 let type_bytes = self.supply_type.serialize(buf);
379 buf.put_f32(self.quantity);
380
381 type_bytes + 4
382 }
383}
384
385impl Serialize for RecordSpecification {
386 fn serialize(&self, buf: &mut BytesMut) -> u16 {
387 buf.put_u32(self.record_sets.len() as u32);
388 let record_sets_bytes: u16 = self
389 .record_sets
390 .iter()
391 .map(|record_set| record_set.serialize(buf))
392 .sum();
393
394 FOUR_OCTETS as u16 + record_sets_bytes
395 }
396}
397
398impl Serialize for RecordSet {
399 fn serialize(&self, buf: &mut BytesMut) -> u16 {
400 buf.put_u32(self.record_id.into());
401 buf.put_u32(self.record_serial_number);
402 buf.put_u32(0u32);
403
404 buf.put_u16(self.record_length_bytes * ONE_BYTE_IN_BITS as u16); buf.put_u16(self.records.len() as u16); let records_bytes = self
407 .records
408 .iter()
409 .map(|record| {
410 buf.put(record.as_slice());
411 record.len()
412 })
413 .sum::<usize>() as u16;
414 let padded_record = length_padded_to_num(records_bytes as usize, EIGHT_OCTETS);
415 buf.put_bytes(0u8, padded_record.padding_length);
416
417 16 + records_bytes + padded_record.padding_length as u16
418 }
419}
420
421#[cfg(test)]
422mod tests {
423 use crate::common::model::PduHeader;
424 use crate::common::Serialize;
425 use crate::constants::PDU_HEADER_LEN_BYTES;
426 use crate::enumerations::{LvcIndicator, PduType};
427 use crate::v7::model::PduStatus;
428 use bytes::BytesMut;
429
430 #[test]
431 fn serialize_header() {
432 let header = PduHeader::new_v6(1, PduType::EntityState)
433 .with_time_stamp(10u32)
434 .with_length(0);
435 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
436
437 header.serialize(&mut buf);
438
439 let expected: [u8; 12] = [
440 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00,
441 ];
442 assert_eq!(buf.as_ref(), expected.as_ref());
443 }
444
445 #[test]
446 fn serialize_header_v7_no_status() {
447 let header = PduHeader::new_v7(1, PduType::EntityState)
448 .with_time_stamp(10u32)
449 .with_length(0);
450 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
451
452 header.serialize(&mut buf);
453
454 let expected: [u8; 12] = [
455 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00,
456 ];
457 assert_eq!(buf.as_ref(), expected.as_ref());
458 }
459
460 #[test]
461 fn serialize_header_v7_with_status() {
462 let header = PduHeader::new_v7(1, PduType::EntityState)
463 .with_time_stamp(10u32)
464 .with_length(0)
465 .with_pdu_status(PduStatus::default().with_lvc_indicator(LvcIndicator::Live));
466 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
467
468 header.serialize(&mut buf);
469
470 let expected: [u8; 12] = [
471 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x02, 0x00,
472 ];
473 assert_eq!(buf.as_ref(), expected.as_ref());
474 }
475}