open_dis_rust/logistics/
repair_response_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.4.7
19pub struct RepairResponsePdu {
20    pub pdu_header: PduHeader,
21    pub receiving_entity_id: EntityId,
22    pub repairing_entity_id: EntityId,
23    pub repair_result: u8,
24    pub padding1: i16,
25    pub padding2: i8,
26}
27
28impl Default for RepairResponsePdu {
29    /// Creates a default Repair Response PDU with arbitrary receiving and repairing entity IDs
30    ///
31    /// # Examples
32    ///
33    /// Initializing a Repair Response PDU:
34    /// ```
35    /// use open_dis_rust::logistics::repair_response_pdu::RepairResponsePdu;
36    /// let repair_response_pdu = RepairResponsePdu::default();
37    /// ```
38    ///
39    fn default() -> Self {
40        RepairResponsePdu {
41            pdu_header: PduHeader::default(PduType::RepairResponse, ProtocolFamily::Logistics, 56),
42            receiving_entity_id: EntityId::default(1),
43            repairing_entity_id: EntityId::default(2),
44            repair_result: 0,
45            padding1: 0,
46            padding2: 0,
47        }
48    }
49}
50
51impl Pdu for RepairResponsePdu {
52    fn serialize(&mut self, buf: &mut BytesMut) {
53        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
54            .expect("The length of the PDU should fit in a u16.");
55        self.pdu_header.serialize(buf);
56        self.receiving_entity_id.serialize(buf);
57        self.repairing_entity_id.serialize(buf);
58        buf.put_u8(self.repair_result);
59        buf.put_i16(self.padding1);
60        buf.put_i8(self.padding2);
61    }
62
63    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
64    where
65        Self: Sized,
66    {
67        let pdu_header = PduHeader::deserialize(&mut buffer);
68        if pdu_header.pdu_type == PduType::RepairResponse {
69            let receiving_entity_id = EntityId::deserialize(&mut buffer);
70            let repairing_entity_id = EntityId::deserialize(&mut buffer);
71            let repair_result = buffer.get_u8();
72            let padding1 = buffer.get_i16();
73            let padding2 = buffer.get_i8();
74
75            Ok(RepairResponsePdu {
76                pdu_header,
77                receiving_entity_id,
78                repairing_entity_id,
79                repair_result,
80                padding1,
81                padding2,
82            })
83        } else {
84            Err(DISError::invalid_header(
85                format!(
86                    "Expected PDU type RepairResponse, got {:?}",
87                    pdu_header.pdu_type
88                ),
89                None,
90            ))
91        }
92    }
93
94    fn as_any(&self) -> &dyn Any {
95        self
96    }
97
98    fn deserialize_without_header(
99        mut buffer: BytesMut,
100        pdu_header: PduHeader,
101    ) -> Result<Self, DISError>
102    where
103        Self: Sized,
104    {
105        let receiving_entity_id = EntityId::deserialize(&mut buffer);
106        let repairing_entity_id = EntityId::deserialize(&mut buffer);
107        let repair_result = buffer.get_u8();
108        let padding1 = buffer.get_i16();
109        let padding2 = buffer.get_i8();
110
111        Ok(RepairResponsePdu {
112            pdu_header,
113            receiving_entity_id,
114            repairing_entity_id,
115            repair_result,
116            padding1,
117            padding2,
118        })
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::RepairResponsePdu;
125    use crate::common::{
126        pdu::Pdu,
127        pdu_header::{PduHeader, PduType, ProtocolFamily},
128    };
129    use bytes::BytesMut;
130
131    #[test]
132    fn create_header() {
133        let repair_response_pdu = RepairResponsePdu::default();
134        let pdu_header =
135            PduHeader::default(PduType::RepairResponse, ProtocolFamily::Logistics, 448 / 8);
136
137        assert_eq!(
138            pdu_header.protocol_version,
139            repair_response_pdu.pdu_header.protocol_version
140        );
141        assert_eq!(
142            pdu_header.exercise_id,
143            repair_response_pdu.pdu_header.exercise_id
144        );
145        assert_eq!(pdu_header.pdu_type, repair_response_pdu.pdu_header.pdu_type);
146        assert_eq!(
147            pdu_header.protocol_family,
148            repair_response_pdu.pdu_header.protocol_family
149        );
150        assert_eq!(pdu_header.length, repair_response_pdu.pdu_header.length);
151        assert_eq!(
152            pdu_header.status_record,
153            repair_response_pdu.pdu_header.status_record
154        );
155    }
156
157    #[test]
158    fn deserialize_header() {
159        let mut repair_response_pdu = RepairResponsePdu::default();
160        let mut buffer = BytesMut::new();
161        repair_response_pdu.serialize(&mut buffer);
162
163        let new_repair_response_pdu = RepairResponsePdu::deserialize(buffer).unwrap();
164        assert_eq!(
165            new_repair_response_pdu.pdu_header,
166            repair_response_pdu.pdu_header
167        );
168    }
169}