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