open_dis_rust/simulation_management/
acknowledge_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    enums::{AcknowledgeFlag, AcknowledgeResponseFlag},
14    pdu::Pdu,
15    pdu_header::{PduHeader, PduType, ProtocolFamily},
16};
17
18#[derive(Copy, Clone, Debug)]
19/// Implemented according to IEEE 1278.1-2012 ยง7.5.6
20pub struct AcknowledgePdu {
21    pub pdu_header: PduHeader,
22    pub originating_entity_id: EntityId,
23    pub receiving_entity_id: EntityId,
24    pub acknowledge_flag: AcknowledgeFlag,
25    pub response_flag: AcknowledgeResponseFlag,
26    pub request_id: u32,
27}
28
29impl Default for AcknowledgePdu {
30    /// Creates a default-initialized Acknowledge PDU
31    ///
32    /// # Examples
33    ///
34    /// Initializing an Acknowledge PDU:
35    /// ```
36    /// use open_dis_rust::simulation_management::acknowledge_pdu::AcknowledgePdu;
37    /// let mut acknowledge_pdu = AcknowledgePdu::default();
38    /// ```
39    ///
40    fn default() -> Self {
41        AcknowledgePdu {
42            pdu_header: PduHeader::default(
43                PduType::Acknowledge,
44                ProtocolFamily::SimulationManagement,
45                32,
46            ),
47            originating_entity_id: EntityId::default(1),
48            receiving_entity_id: EntityId::default(2),
49            acknowledge_flag: AcknowledgeFlag::default(),
50            response_flag: AcknowledgeResponseFlag::default(),
51            request_id: 0,
52        }
53    }
54}
55
56impl Pdu for AcknowledgePdu {
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_u16(self.acknowledge_flag as u16);
64        buf.put_u16(self.response_flag as u16);
65        buf.put_u32(self.request_id);
66    }
67
68    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
69    where
70        Self: Sized,
71    {
72        let pdu_header = PduHeader::deserialize(&mut buffer);
73        if pdu_header.pdu_type == PduType::Acknowledge {
74            let originating_entity_id = EntityId::deserialize(&mut buffer);
75            let receiving_entity_id = EntityId::deserialize(&mut buffer);
76            let acknowledge_flag = AcknowledgeFlag::deserialize(&mut buffer);
77            let response_flag = AcknowledgeResponseFlag::deserialize(&mut buffer);
78            let request_id = buffer.get_u32();
79
80            Ok(AcknowledgePdu {
81                pdu_header,
82                originating_entity_id,
83                receiving_entity_id,
84                acknowledge_flag,
85                response_flag,
86                request_id,
87            })
88        } else {
89            Err(DISError::invalid_header(
90                format!(
91                    "Expected PDU type Acknowledge, got {:?}",
92                    pdu_header.pdu_type
93                ),
94                None,
95            ))
96        }
97    }
98
99    fn as_any(&self) -> &dyn Any {
100        self
101    }
102
103    fn deserialize_without_header(
104        mut buffer: BytesMut,
105        pdu_header: PduHeader,
106    ) -> Result<Self, DISError>
107    where
108        Self: Sized,
109    {
110        let originating_entity_id = EntityId::deserialize(&mut buffer);
111        let receiving_entity_id = EntityId::deserialize(&mut buffer);
112        let acknowledge_flag = AcknowledgeFlag::deserialize(&mut buffer);
113        let response_flag = AcknowledgeResponseFlag::deserialize(&mut buffer);
114        let request_id = buffer.get_u32();
115
116        Ok(AcknowledgePdu {
117            pdu_header,
118            originating_entity_id,
119            receiving_entity_id,
120            acknowledge_flag,
121            response_flag,
122            request_id,
123        })
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::AcknowledgePdu;
130    use crate::common::{
131        pdu::Pdu,
132        pdu_header::{PduHeader, PduType, ProtocolFamily},
133    };
134    use bytes::BytesMut;
135
136    #[test]
137    fn create_header() {
138        let acknowledge_pdu = AcknowledgePdu::default();
139        let pdu_header = PduHeader::default(
140            PduType::Acknowledge,
141            ProtocolFamily::SimulationManagement,
142            32,
143        );
144
145        assert_eq!(
146            pdu_header.protocol_version,
147            acknowledge_pdu.pdu_header.protocol_version
148        );
149        assert_eq!(
150            pdu_header.exercise_id,
151            acknowledge_pdu.pdu_header.exercise_id
152        );
153        assert_eq!(pdu_header.pdu_type, acknowledge_pdu.pdu_header.pdu_type);
154        assert_eq!(
155            pdu_header.protocol_family,
156            acknowledge_pdu.pdu_header.protocol_family
157        );
158        assert_eq!(pdu_header.length, acknowledge_pdu.pdu_header.length);
159        assert_eq!(
160            pdu_header.status_record,
161            acknowledge_pdu.pdu_header.status_record
162        );
163    }
164
165    #[test]
166    fn cast_to_any() {
167        let acknowledge_pdu = AcknowledgePdu::default();
168        let any_pdu = acknowledge_pdu.as_any();
169
170        assert!(any_pdu.is::<AcknowledgePdu>());
171    }
172
173    #[test]
174    fn deserialize_header() {
175        let mut acknowledge_pdu = AcknowledgePdu::default();
176        let mut buffer = BytesMut::new();
177        acknowledge_pdu.serialize(&mut buffer);
178
179        let new_acknowledge_pdu = AcknowledgePdu::deserialize(buffer).unwrap();
180        assert_eq!(new_acknowledge_pdu.pdu_header, acknowledge_pdu.pdu_header);
181    }
182}