dis_rs/common/
writer.rs

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    /// Serializes `self` into the buffer.
44    ///
45    /// Fails when the capacity of the buffer is smaller than the serialized length of the PDU (header + body).
46    ///
47    /// # Errors
48    /// Returns a `DisError` when parsing fails
49    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::IntercomSignal(body) => { body.serialize_pdu(version, buf) }
91            // PduBody::IntercomControl(body) => { body.serialize_pdu(version, buf) }
92            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::MinefieldState(body) => { body.serialize_pdu(version, buf) }
97            // PduBody::MinefieldQuery(body) => { body.serialize_pdu(version, buf) }
98            // PduBody::MinefieldData(body) => { body.serialize_pdu(version, buf) }
99            // PduBody::MinefieldResponseNACK(body) => { body.serialize_pdu(version, buf) }
100            // PduBody::EnvironmentalProcess(body) => { body.serialize_pdu(version, buf) }
101            // PduBody::GriddedData(body) => { body.serialize_pdu(version, buf) }
102            // PduBody::PointObjectState(body) => { body.serialize_pdu(version, buf) }
103            // PduBody::LinearObjectState(body) => { body.serialize_pdu(version, buf) }
104            // PduBody::ArealObjectState(body) => { body.serialize_pdu(version, buf) }
105            // PduBody::TSPI(body) => { body.serialize_pdu(version, buf) }
106            // PduBody::Appearance(body) => { body.serialize_pdu(version, buf) }
107            // PduBody::ArticulatedParts(body) => { body.serialize_pdu(version, buf) }
108            // PduBody::LEFire(body) => { body.serialize_pdu(version, buf) }
109            // PduBody::LEDetonation(body) => { body.serialize_pdu(version, buf) }
110            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::DirectedEnergyFire(body) => { body.serialize_pdu(version, buf) }
128            // PduBody::EntityDamageStatus(body) => { body.serialize_pdu(version, buf) }
129            // PduBody::InformationOperationsAction(body) => { body.serialize_pdu(version, buf) }
130            // PduBody::InformationOperationsReport(body) => { body.serialize_pdu(version, buf) }
131            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); // record length in bits
405        buf.put_u16(self.records.len() as u16); // record count
406        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}