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