open_dis_rust/simulation_management_with_reliability/
data_query_reliable_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.11.9
18pub struct DataQueryReliablePdu {
19    pub pdu_header: PduHeader,
20    pub originating_entity_id: EntityId,
21    pub receiving_entity_id: EntityId,
22    pub required_reliability_service: u8,
23    pub pad1: u16,
24    pub pad2: u8,
25    pub request_id: u32,
26    pub time_interval: u32,
27    pub number_of_fixed_datum_records: u32,
28    pub number_of_variable_datum_records: u32,
29    pub fixed_datum_records: u64,
30    pub variable_datum_records: u64,
31}
32
33impl Default for DataQueryReliablePdu {
34    fn default() -> Self {
35        DataQueryReliablePdu {
36            pdu_header: PduHeader::default(
37                PduType::DataQueryReliable,
38                ProtocolFamily::SimulationManagementWithReliability,
39                56,
40            ),
41            originating_entity_id: EntityId::default(1),
42            receiving_entity_id: EntityId::default(2),
43            required_reliability_service: 0,
44            pad1: 0,
45            pad2: 0,
46            request_id: 0,
47            time_interval: 0,
48            number_of_fixed_datum_records: 0,
49            number_of_variable_datum_records: 0,
50            fixed_datum_records: 0,
51            variable_datum_records: 0,
52        }
53    }
54}
55
56impl Pdu for DataQueryReliablePdu {
57    fn serialize(&mut self, buf: &mut BytesMut) {
58        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
59            .expect("The length of the PDU should fit in a u16.");
60        self.pdu_header.serialize(buf);
61        self.originating_entity_id.serialize(buf);
62        self.receiving_entity_id.serialize(buf);
63        buf.put_u8(self.required_reliability_service);
64        buf.put_u16(self.pad1);
65        buf.put_u8(self.pad2);
66        buf.put_u32(self.request_id);
67        buf.put_u32(self.time_interval);
68        buf.put_u32(self.number_of_fixed_datum_records);
69        buf.put_u32(self.number_of_variable_datum_records);
70        buf.put_u64(self.fixed_datum_records);
71        buf.put_u64(self.variable_datum_records);
72    }
73
74    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
75    where
76        Self: Sized,
77    {
78        let pdu_header = PduHeader::deserialize(&mut buffer);
79        if pdu_header.pdu_type == PduType::DataQueryReliable {
80            let originating_entity_id = EntityId::deserialize(&mut buffer);
81            let receiving_entity_id = EntityId::deserialize(&mut buffer);
82            let required_reliability_service = buffer.get_u8();
83            let pad1 = buffer.get_u16();
84            let pad2 = buffer.get_u8();
85            let request_id = buffer.get_u32();
86            let time_interval = buffer.get_u32();
87            let number_of_fixed_datum_records = buffer.get_u32();
88            let number_of_variable_datum_records = buffer.get_u32();
89            let mut fixed_datum_records: u64 = 0;
90            for _record in 0..number_of_fixed_datum_records as usize {
91                fixed_datum_records += buffer.get_u64();
92            }
93            let mut variable_datum_records: u64 = 0;
94            for _record in 0..number_of_variable_datum_records as usize {
95                variable_datum_records += buffer.get_u64();
96            }
97
98            Ok(DataQueryReliablePdu {
99                pdu_header,
100                originating_entity_id,
101                receiving_entity_id,
102                required_reliability_service,
103                pad1,
104                pad2,
105                request_id,
106                time_interval,
107                number_of_fixed_datum_records,
108                number_of_variable_datum_records,
109                fixed_datum_records,
110                variable_datum_records,
111            })
112        } else {
113            Err(DISError::invalid_header(
114                format!(
115                    "Expected PDU type DataQueryReliable, got {:?}",
116                    pdu_header.pdu_type
117                ),
118                None,
119            ))
120        }
121    }
122
123    fn as_any(&self) -> &dyn Any {
124        self
125    }
126
127    fn deserialize_without_header(
128        mut buffer: BytesMut,
129        pdu_header: PduHeader,
130    ) -> Result<Self, DISError>
131    where
132        Self: Sized,
133    {
134        let originating_entity_id = EntityId::deserialize(&mut buffer);
135        let receiving_entity_id = EntityId::deserialize(&mut buffer);
136        let required_reliability_service = buffer.get_u8();
137        let pad1 = buffer.get_u16();
138        let pad2 = buffer.get_u8();
139        let request_id = buffer.get_u32();
140        let time_interval = buffer.get_u32();
141        let number_of_fixed_datum_records = buffer.get_u32();
142        let number_of_variable_datum_records = buffer.get_u32();
143        let mut fixed_datum_records: u64 = 0;
144        for _record in 0..number_of_fixed_datum_records as usize {
145            fixed_datum_records += buffer.get_u64();
146        }
147        let mut variable_datum_records: u64 = 0;
148        for _record in 0..number_of_variable_datum_records as usize {
149            variable_datum_records += buffer.get_u64();
150        }
151
152        Ok(DataQueryReliablePdu {
153            pdu_header,
154            originating_entity_id,
155            receiving_entity_id,
156            required_reliability_service,
157            pad1,
158            pad2,
159            request_id,
160            time_interval,
161            number_of_fixed_datum_records,
162            number_of_variable_datum_records,
163            fixed_datum_records,
164            variable_datum_records,
165        })
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::DataQueryReliablePdu;
172    use crate::common::pdu_header::{PduHeader, PduType, ProtocolFamily};
173
174    #[test]
175    fn create_header() {
176        let data_query_reliable_pdu = DataQueryReliablePdu::default();
177        let pdu_header = PduHeader::default(
178            PduType::DataQueryReliable,
179            ProtocolFamily::SimulationManagementWithReliability,
180            448 / 8,
181        );
182
183        assert_eq!(
184            pdu_header.protocol_version,
185            data_query_reliable_pdu.pdu_header.protocol_version
186        );
187        assert_eq!(
188            pdu_header.exercise_id,
189            data_query_reliable_pdu.pdu_header.exercise_id
190        );
191        assert_eq!(
192            pdu_header.pdu_type,
193            data_query_reliable_pdu.pdu_header.pdu_type
194        );
195        assert_eq!(
196            pdu_header.protocol_family,
197            data_query_reliable_pdu.pdu_header.protocol_family
198        );
199        assert_eq!(pdu_header.length, data_query_reliable_pdu.pdu_header.length);
200        assert_eq!(
201            pdu_header.status_record,
202            data_query_reliable_pdu.pdu_header.status_record
203        );
204    }
205}