1use crate::DisError;
2use crate::common::model::{
3 ArticulatedPart, AttachedPart, BeamData, ClockTime, EntityAssociationParameter, EntityId,
4 EntityTypeParameter, EventId, ExpendableDescriptor, ExplosionDescriptor, FixedDatum, Location,
5 MunitionDescriptor, Orientation, SeparationParameter, SimulationAddress, VariableDatum,
6 VariableParameter, VectorF32, length_padded_to_num,
7};
8use crate::common::model::{Pdu, PduBody, PduHeader};
9use crate::common::{Serialize, SerializePdu, SupportedVersion};
10use crate::constants::{EIGHT_OCTETS, FOUR_OCTETS, ONE_BYTE_IN_BITS, PDU_HEADER_LEN_BYTES};
11use crate::enumerations::{ProtocolVersion, VariableParameterRecordType};
12use crate::model::{RecordSet, RecordSpecification, SupplyQuantity};
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.timestamp.into());
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 MunitionDescriptor {
191 fn serialize(&self, buf: &mut BytesMut) -> u16 {
192 let entity_bytes = self.entity_type.serialize(buf);
193 buf.put_u16(self.warhead.into());
194 buf.put_u16(self.fuse.into());
195 buf.put_u16(self.quantity);
196 buf.put_u16(self.rate);
197 entity_bytes + 8
198 }
199}
200
201impl Serialize for ExplosionDescriptor {
202 fn serialize(&self, buf: &mut BytesMut) -> u16 {
203 let entity_bytes = self.entity_type.serialize(buf);
204 buf.put_u16(self.explosive_material.into());
205 buf.put_u16(0u16);
206 buf.put_f32(self.explosive_force);
207 entity_bytes + 8
208 }
209}
210
211impl Serialize for ExpendableDescriptor {
212 fn serialize(&self, buf: &mut BytesMut) -> u16 {
213 let entity_bytes = self.entity_type.serialize(buf);
214 buf.put_u64(0u64);
215 entity_bytes + 8
216 }
217}
218
219impl Serialize for ClockTime {
220 fn serialize(&self, buf: &mut BytesMut) -> u16 {
221 buf.put_i32(self.hour);
222 buf.put_u32(self.time_past_hour);
223 8
224 }
225}
226
227impl Serialize for FixedDatum {
228 fn serialize(&self, buf: &mut BytesMut) -> u16 {
229 buf.put_u32(self.datum_id.into());
230 buf.put_u32(self.datum_value);
231
232 8
233 }
234}
235
236impl Serialize for VariableDatum {
237 #[allow(clippy::cast_possible_truncation)]
238 fn serialize(&self, buf: &mut BytesMut) -> u16 {
239 const ALIGNMENT_BYTES: usize = 8; let data_length_bytes: usize = self.datum_value.len();
242 let padded = length_padded_to_num(data_length_bytes, ALIGNMENT_BYTES);
243 let padding_length_bytes = padded.padding_length;
244
245 buf.put_u32(self.datum_id.into());
246 buf.put_u32((data_length_bytes * 8) as u32);
247 buf.put_slice(&self.datum_value);
248 buf.put_bytes(0, padding_length_bytes);
249
250 8 + padded.record_length as u16
251 }
252}
253
254impl Serialize for VariableParameter {
255 fn serialize(&self, buf: &mut BytesMut) -> u16 {
256 match self {
257 VariableParameter::Articulated(inner) => {
258 buf.put_u8(VariableParameterRecordType::ArticulatedPart.into());
259 1 + inner.serialize(buf)
260 }
261 VariableParameter::Attached(inner) => {
262 buf.put_u8(VariableParameterRecordType::AttachedPart.into());
263 1 + inner.serialize(buf)
264 }
265 VariableParameter::Separation(inner) => {
266 buf.put_u8(VariableParameterRecordType::Separation.into());
267 1 + inner.serialize(buf)
268 }
269 VariableParameter::EntityType(inner) => {
270 buf.put_u8(VariableParameterRecordType::EntityType.into());
271 1 + inner.serialize(buf)
272 }
273 VariableParameter::EntityAssociation(inner) => {
274 buf.put_u8(VariableParameterRecordType::EntityAssociation.into());
275 1 + inner.serialize(buf)
276 }
277 VariableParameter::Unspecified(parameter_type, value) => {
278 buf.put_u8(*parameter_type);
279 buf.put(&value[..]);
280 16
281 }
282 }
283 }
284}
285
286impl Serialize for ArticulatedPart {
287 fn serialize(&self, buf: &mut BytesMut) -> u16 {
288 buf.put_u8(self.change_indicator);
289 buf.put_u16(self.attachment_id);
290 let type_class: u32 = self.type_class.into();
291 let type_metric: u32 = self.type_metric.into();
292 buf.put_u32(type_class + type_metric);
293 buf.put_f32(self.parameter_value);
294 buf.put_u32(0u32);
295
296 15
297 }
298}
299
300impl Serialize for AttachedPart {
301 fn serialize(&self, buf: &mut BytesMut) -> u16 {
302 buf.put_u8(self.detached_indicator.into());
303 buf.put_u16(self.attachment_id);
304 buf.put_u32(self.parameter_type.into());
305 self.attached_part_type.serialize(buf);
306
307 15
308 }
309}
310
311impl Serialize for SeparationParameter {
312 fn serialize(&self, buf: &mut BytesMut) -> u16 {
313 buf.put_u8(self.reason.into());
314 buf.put_u8(self.pre_entity_indicator.into());
315 buf.put_u8(0u8);
316 self.parent_entity_id.serialize(buf);
317 buf.put_u16(0u16);
318 buf.put_u16(self.station_name.into());
319 buf.put_u16(self.station_number);
320
321 15
322 }
323}
324
325impl Serialize for EntityTypeParameter {
326 fn serialize(&self, buf: &mut BytesMut) -> u16 {
327 buf.put_u8(self.change_indicator.into());
328 self.entity_type.serialize(buf);
329 buf.put_u16(0u16);
330 buf.put_u32(0u32);
331
332 15
333 }
334}
335
336impl Serialize for EntityAssociationParameter {
337 fn serialize(&self, buf: &mut BytesMut) -> u16 {
338 buf.put_u8(self.change_indicator.into());
339 buf.put_u8(self.association_status.into());
340 buf.put_u8(self.association_type.into());
341 self.entity_id.serialize(buf);
342 buf.put_u16(self.own_station_location.into());
343 buf.put_u8(self.physical_connection_type.into());
344 buf.put_u8(self.group_member_type.into());
345 buf.put_u16(self.group_number);
346
347 15
348 }
349}
350
351impl Serialize for BeamData {
352 fn serialize(&self, buf: &mut BytesMut) -> u16 {
353 buf.put_f32(self.azimuth_center);
354 buf.put_f32(self.azimuth_sweep);
355 buf.put_f32(self.elevation_center);
356 buf.put_f32(self.elevation_sweep);
357 buf.put_f32(self.sweep_sync);
358
359 20
360 }
361}
362
363impl Serialize for SupplyQuantity {
364 fn serialize(&self, buf: &mut BytesMut) -> u16 {
365 let type_bytes = self.supply_type.serialize(buf);
366 buf.put_f32(self.quantity);
367
368 type_bytes + 4
369 }
370}
371
372impl Serialize for RecordSpecification {
373 fn serialize(&self, buf: &mut BytesMut) -> u16 {
374 buf.put_u32(self.record_sets.len() as u32);
375 let record_sets_bytes: u16 = self
376 .record_sets
377 .iter()
378 .map(|record_set| record_set.serialize(buf))
379 .sum();
380
381 FOUR_OCTETS as u16 + record_sets_bytes
382 }
383}
384
385impl Serialize for RecordSet {
386 fn serialize(&self, buf: &mut BytesMut) -> u16 {
387 buf.put_u32(self.record_id.into());
388 buf.put_u32(self.record_serial_number);
389 buf.put_u32(0u32);
390
391 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
394 .records
395 .iter()
396 .map(|record| {
397 buf.put(record.as_slice());
398 record.len()
399 })
400 .sum::<usize>() as u16;
401 let padded_record = length_padded_to_num(records_bytes as usize, EIGHT_OCTETS);
402 buf.put_bytes(0u8, padded_record.padding_length);
403
404 16 + records_bytes + padded_record.padding_length as u16
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use crate::common::Serialize;
411 use crate::common::model::{PduHeader, Timestamp};
412 use crate::constants::PDU_HEADER_LEN_BYTES;
413 use crate::enumerations::{LvcIndicator, PduType};
414 use crate::v7::model::PduStatus;
415 use alloc::vec;
416 use bytes::BytesMut;
417
418 #[test]
419 fn serialize_header() {
420 let header = PduHeader::new_v6(1, PduType::EntityState)
421 .with_timestamp(Timestamp::new(10u32))
422 .with_length(0);
423 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
424
425 header.serialize(&mut buf);
426
427 let expected: [u8; 12] = [
428 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00,
429 ];
430 assert_eq!(buf.as_ref(), expected.as_ref());
431 }
432
433 #[test]
434 fn serialize_header_v7_no_status() {
435 let header = PduHeader::new_v7(1, PduType::EntityState)
436 .with_timestamp(Timestamp::new(10u32))
437 .with_length(0);
438 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
439
440 header.serialize(&mut buf);
441
442 let expected: [u8; 12] = [
443 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00,
444 ];
445 assert_eq!(buf.as_ref(), expected.as_ref());
446 }
447
448 #[test]
449 fn serialize_header_v7_with_status() {
450 let header = PduHeader::new_v7(1, PduType::EntityState)
451 .with_timestamp(Timestamp::new(10u32))
452 .with_length(0)
453 .with_pdu_status(PduStatus::default().with_lvc_indicator(LvcIndicator::Live));
454 let mut buf = BytesMut::with_capacity(PDU_HEADER_LEN_BYTES as usize);
455
456 header.serialize(&mut buf);
457
458 let expected: [u8; 12] = [
459 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x02, 0x00,
460 ];
461 assert_eq!(buf.as_ref(), expected.as_ref());
462 }
463
464 #[test]
465 fn serialize_variable_datum() {
466 use crate::enumerations::VariableRecordType;
467 use crate::model::VariableDatum;
468
469 let variable_datum = VariableDatum::new(VariableRecordType::Unspecified(1), vec![1, 2]);
470
471 let mut buf = BytesMut::new();
472 variable_datum.serialize(&mut buf);
473
474 let expected = [
475 0, 0, 0, 1, 0, 0, 0, 16, 1, 2, 0, 0, 0, 0, 0, 0, ];
481
482 assert_eq!(buf.as_ref(), expected.as_ref());
483 }
484}