open_dis_rust/simulation_management/
set_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.10
18pub struct SetDataPdu {
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 SetDataPdu {
31    fn default() -> Self {
32        SetDataPdu {
33            pdu_header: PduHeader::default(
34                PduType::SetData,
35                ProtocolFamily::SimulationManagement,
36                56,
37            ),
38            originating_entity_id: EntityId::default(1),
39            receiving_entity_id: EntityId::default(2),
40            request_id: 0,
41            padding: 0,
42            number_of_fixed_datum_records: 0,
43            number_of_variable_datum_records: 0,
44            fixed_datum_records: 0,
45            variable_datum_records: 0,
46        }
47    }
48}
49
50impl Pdu for SetDataPdu {
51    fn serialize(&mut self, buf: &mut BytesMut) {
52        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
53            .expect("The length of the PDU should fit in a u16.");
54        self.pdu_header.serialize(buf);
55        self.originating_entity_id.serialize(buf);
56        self.receiving_entity_id.serialize(buf);
57        buf.put_u32(self.request_id);
58        buf.put_u32(self.padding);
59        buf.put_u32(self.number_of_fixed_datum_records);
60        buf.put_u32(self.number_of_variable_datum_records);
61        buf.put_u64(self.fixed_datum_records);
62        buf.put_u64(self.variable_datum_records);
63    }
64
65    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
66    where
67        Self: Sized,
68    {
69        let pdu_header = PduHeader::decode(&mut buffer);
70        if pdu_header.pdu_type == PduType::SetData {
71            let originating_entity_id = EntityId::decode(&mut buffer);
72            let receiving_entity_id = EntityId::decode(&mut buffer);
73            let request_id = buffer.get_u32();
74            let padding = buffer.get_u32();
75            let number_of_fixed_datum_records = buffer.get_u32();
76            let number_of_variable_datum_records = buffer.get_u32();
77            let mut fixed_datum_records: u64 = 0;
78            for _record in 0..number_of_fixed_datum_records as usize {
79                fixed_datum_records += buffer.get_u64();
80            }
81            let mut variable_datum_records: u64 = 0;
82            for _record in 0..number_of_variable_datum_records as usize {
83                variable_datum_records += buffer.get_u64();
84            }
85
86            Ok(SetDataPdu {
87                pdu_header,
88                originating_entity_id,
89                receiving_entity_id,
90                request_id,
91                padding,
92                number_of_fixed_datum_records,
93                number_of_variable_datum_records,
94                fixed_datum_records,
95                variable_datum_records,
96            })
97        } else {
98            Err(DISError::InvalidDISHeader)
99        }
100    }
101
102    fn as_any(&self) -> &dyn Any {
103        self
104    }
105
106    fn deserialize_without_header(
107        mut buffer: BytesMut,
108        pdu_header: PduHeader,
109    ) -> Result<Self, DISError>
110    where
111        Self: Sized,
112    {
113        let originating_entity_id = EntityId::decode(&mut buffer);
114        let receiving_entity_id = EntityId::decode(&mut buffer);
115        let request_id = buffer.get_u32();
116        let padding = buffer.get_u32();
117        let number_of_fixed_datum_records = buffer.get_u32();
118        let number_of_variable_datum_records = buffer.get_u32();
119        let mut fixed_datum_records: u64 = 0;
120        for _record in 0..number_of_fixed_datum_records as usize {
121            fixed_datum_records += buffer.get_u64();
122        }
123        let mut variable_datum_records: u64 = 0;
124        for _record in 0..number_of_variable_datum_records as usize {
125            variable_datum_records += buffer.get_u64();
126        }
127
128        Ok(SetDataPdu {
129            pdu_header,
130            originating_entity_id,
131            receiving_entity_id,
132            request_id,
133            padding,
134            number_of_fixed_datum_records,
135            number_of_variable_datum_records,
136            fixed_datum_records,
137            variable_datum_records,
138        })
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::SetDataPdu;
145    use crate::common::{
146        pdu::Pdu,
147        pdu_header::{PduHeader, PduType, ProtocolFamily},
148    };
149    use bytes::BytesMut;
150
151    #[test]
152    fn create_header() {
153        let set_data_pdu = SetDataPdu::default();
154        let pdu_header = PduHeader::default(
155            PduType::SetData,
156            ProtocolFamily::SimulationManagement,
157            448 / 8,
158        );
159
160        assert_eq!(
161            pdu_header.protocol_version,
162            set_data_pdu.pdu_header.protocol_version
163        );
164        assert_eq!(pdu_header.exercise_id, set_data_pdu.pdu_header.exercise_id);
165        assert_eq!(pdu_header.pdu_type, set_data_pdu.pdu_header.pdu_type);
166        assert_eq!(
167            pdu_header.protocol_family,
168            set_data_pdu.pdu_header.protocol_family
169        );
170        assert_eq!(pdu_header.length, set_data_pdu.pdu_header.length);
171        assert_eq!(pdu_header.padding, set_data_pdu.pdu_header.padding);
172    }
173
174    #[test]
175    fn deserialize_header() {
176        let mut set_data_pdu = SetDataPdu::default();
177        let mut buffer = BytesMut::new();
178        set_data_pdu.serialize(&mut buffer);
179
180        let new_set_data_pdu = SetDataPdu::deserialize(buffer).unwrap();
181        assert_eq!(new_set_data_pdu.pdu_header, set_data_pdu.pdu_header);
182    }
183}