open_dis_rust/simulation_management/
data_pdu.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2023 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7use crate::common::{
8    dis_error::DISError,
9    entity_id::EntityId,
10    pdu::Pdu,
11    pdu_header::{PduHeader, PduType, ProtocolFamily},
12};
13use bytes::{Buf, BufMut, BytesMut};
14use std::any::Any;
15
16#[derive(Copy, Clone, Debug)]
17/// Implemented according to IEEE 1278.1-2012 ยง7.5.11
18pub struct DataPdu {
19    pub pdu_header: PduHeader,
20    pub originating_entity_id: EntityId,
21    pub receiving_entity_id: EntityId,
22    pub request_id: u32,
23    pub padding: u32,
24    pub number_of_fixed_datum_records: u32,
25    pub number_of_variable_datum_records: u32,
26    pub fixed_datum_records: u64,
27    pub variable_datum_records: u64,
28}
29
30impl Default for DataPdu {
31    fn default() -> Self {
32        DataPdu {
33            pdu_header: PduHeader::default(PduType::Data, ProtocolFamily::SimulationManagement, 56),
34            originating_entity_id: EntityId::default(1),
35            receiving_entity_id: EntityId::default(2),
36            request_id: 0,
37            padding: 0,
38            number_of_fixed_datum_records: 0,
39            number_of_variable_datum_records: 0,
40            fixed_datum_records: 0,
41            variable_datum_records: 0,
42        }
43    }
44}
45
46impl Pdu for DataPdu {
47    fn serialize(&mut self, buf: &mut BytesMut) {
48        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
49            .expect("The length of the PDU should fit in a u16.");
50        self.pdu_header.serialize(buf);
51        self.originating_entity_id.serialize(buf);
52        self.receiving_entity_id.serialize(buf);
53        buf.put_u32(self.request_id);
54        buf.put_u32(self.padding);
55        buf.put_u32(self.number_of_fixed_datum_records);
56        buf.put_u32(self.number_of_variable_datum_records);
57        buf.put_u64(self.fixed_datum_records);
58        buf.put_u64(self.variable_datum_records);
59    }
60
61    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
62    where
63        Self: Sized,
64    {
65        let pdu_header = PduHeader::deserialize(&mut buffer);
66        if pdu_header.pdu_type == PduType::Data {
67            let originating_entity_id = EntityId::deserialize(&mut buffer);
68            let receiving_entity_id = EntityId::deserialize(&mut buffer);
69            let request_id = buffer.get_u32();
70            let padding = buffer.get_u32();
71            let number_of_fixed_datum_records = buffer.get_u32();
72            let number_of_variable_datum_records = buffer.get_u32();
73            let mut fixed_datum_records: u64 = 0;
74            for _record in 0..number_of_fixed_datum_records as usize {
75                fixed_datum_records += buffer.get_u64();
76            }
77            let mut variable_datum_records: u64 = 0;
78            for _record in 0..number_of_variable_datum_records as usize {
79                variable_datum_records += buffer.get_u64();
80            }
81
82            Ok(DataPdu {
83                pdu_header,
84                originating_entity_id,
85                receiving_entity_id,
86                request_id,
87                padding,
88                number_of_fixed_datum_records,
89                number_of_variable_datum_records,
90                fixed_datum_records,
91                variable_datum_records,
92            })
93        } else {
94            Err(DISError::invalid_header(
95                format!("Expected PDU type Data, got {:?}", pdu_header.pdu_type),
96                None,
97            ))
98        }
99    }
100
101    fn as_any(&self) -> &dyn Any {
102        self
103    }
104
105    fn deserialize_without_header(
106        mut buffer: BytesMut,
107        pdu_header: PduHeader,
108    ) -> Result<Self, DISError>
109    where
110        Self: Sized,
111    {
112        let originating_entity_id = EntityId::deserialize(&mut buffer);
113        let receiving_entity_id = EntityId::deserialize(&mut buffer);
114        let request_id = buffer.get_u32();
115        let padding = buffer.get_u32();
116        let number_of_fixed_datum_records = buffer.get_u32();
117        let number_of_variable_datum_records = buffer.get_u32();
118        let mut fixed_datum_records: u64 = 0;
119        for _record in 0..number_of_fixed_datum_records as usize {
120            fixed_datum_records += buffer.get_u64();
121        }
122        let mut variable_datum_records: u64 = 0;
123        for _record in 0..number_of_variable_datum_records as usize {
124            variable_datum_records += buffer.get_u64();
125        }
126
127        Ok(DataPdu {
128            pdu_header,
129            originating_entity_id,
130            receiving_entity_id,
131            request_id,
132            padding,
133            number_of_fixed_datum_records,
134            number_of_variable_datum_records,
135            fixed_datum_records,
136            variable_datum_records,
137        })
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::DataPdu;
144    use crate::common::{
145        pdu::Pdu,
146        pdu_header::{PduHeader, PduType, ProtocolFamily},
147    };
148    use bytes::BytesMut;
149
150    #[test]
151    fn create_header() {
152        let data_pdu = DataPdu::default();
153        let pdu_header =
154            PduHeader::default(PduType::Data, ProtocolFamily::SimulationManagement, 448 / 8);
155
156        assert_eq!(
157            pdu_header.protocol_version,
158            data_pdu.pdu_header.protocol_version
159        );
160        assert_eq!(pdu_header.exercise_id, data_pdu.pdu_header.exercise_id);
161        assert_eq!(pdu_header.pdu_type, data_pdu.pdu_header.pdu_type);
162        assert_eq!(
163            pdu_header.protocol_family,
164            data_pdu.pdu_header.protocol_family
165        );
166        assert_eq!(pdu_header.length, data_pdu.pdu_header.length);
167        assert_eq!(pdu_header.status_record, data_pdu.pdu_header.status_record);
168    }
169
170    #[test]
171    fn deserialize_header() {
172        let mut data_pdu = DataPdu::default();
173        let mut buffer = BytesMut::new();
174        data_pdu.serialize(&mut buffer);
175
176        let new_data_pdu = DataPdu::deserialize(buffer).unwrap();
177        assert_eq!(new_data_pdu.pdu_header, data_pdu.pdu_header);
178    }
179}