open_dis_rust/entity_management/
transfer_ownership_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    simulation_address::SimulationAddress,
16};
17
18use super::data_types::record_specification::RecordSpecification;
19
20#[derive(Clone, Debug)]
21/// Implemented according to IEEE 1278.1-2012 ยง7.8.4
22pub struct TransferOwnershipPdu {
23    pub pdu_header: PduHeader,
24    pub originating_id: SimulationAddress,
25    pub receiving_id: SimulationAddress,
26    pub request_id: u32,
27    pub required_reliability_service: u8,
28    pub transfer_type: u8,
29    pub transfer_entity_id: EntityId,
30    pub record_information: RecordSpecification,
31}
32
33impl Default for TransferOwnershipPdu {
34    /// Creates a default Transfer Ownership PDU with arbitrary originating and receiving IDs
35    ///
36    /// # Examples
37    ///
38    /// Initializing a Transfer Ownership PDU:
39    /// ```
40    /// use open_dis_rust::entity_management::transfer_ownership_pdu::TransferOwnershipPdu;
41    /// let transfer_ownership_pdu = TransferOwnershipPdu::default();
42    /// ```
43    ///
44    fn default() -> Self {
45        TransferOwnershipPdu {
46            pdu_header: PduHeader::default(
47                PduType::TransferOwnership,
48                ProtocolFamily::EntityManagement,
49                56,
50            ),
51            originating_id: SimulationAddress::default(),
52            receiving_id: SimulationAddress::default(),
53            request_id: 0,
54            required_reliability_service: 0,
55            transfer_type: 0,
56            transfer_entity_id: EntityId::default(1),
57            record_information: RecordSpecification::default(),
58        }
59    }
60}
61
62impl Pdu for TransferOwnershipPdu {
63    fn serialize(&mut self, buf: &mut BytesMut) {
64        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
65            .expect("The length of the PDU should fit in a u16.");
66        self.pdu_header.serialize(buf);
67        self.originating_id.serialize(buf);
68        self.receiving_id.serialize(buf);
69        buf.put_u32(self.request_id);
70        buf.put_u8(self.required_reliability_service);
71        buf.put_u8(self.transfer_type);
72        self.transfer_entity_id.serialize(buf);
73        self.record_information.serialize(buf);
74    }
75
76    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
77    where
78        Self: Sized,
79    {
80        let pdu_header = PduHeader::deserialize(&mut buffer);
81        if pdu_header.pdu_type == PduType::TransferOwnership {
82            let originating_id = SimulationAddress::deserialize(&mut buffer);
83            let receiving_id = SimulationAddress::deserialize(&mut buffer);
84            let request_id = buffer.get_u32();
85            let required_reliability_service = buffer.get_u8();
86            let transfer_type = buffer.get_u8();
87            let transfer_entity_id = EntityId::deserialize(&mut buffer);
88            let record_information = RecordSpecification::deserialize(&mut buffer);
89            Ok(TransferOwnershipPdu {
90                pdu_header,
91                originating_id,
92                receiving_id,
93                request_id,
94                required_reliability_service,
95                transfer_type,
96                transfer_entity_id,
97                record_information,
98            })
99        } else {
100            Err(DISError::invalid_header(
101                format!(
102                    "Expected PDU type TransferOwnership, got {:?}",
103                    pdu_header.pdu_type
104                ),
105                None,
106            ))
107        }
108    }
109
110    fn as_any(&self) -> &dyn Any {
111        self
112    }
113
114    fn deserialize_without_header(
115        mut buffer: BytesMut,
116        pdu_header: PduHeader,
117    ) -> Result<Self, DISError>
118    where
119        Self: Sized,
120    {
121        let originating_id = SimulationAddress::deserialize(&mut buffer);
122        let receiving_id = SimulationAddress::deserialize(&mut buffer);
123        let request_id = buffer.get_u32();
124        let required_reliability_service = buffer.get_u8();
125        let transfer_type = buffer.get_u8();
126        let transfer_entity_id = EntityId::deserialize(&mut buffer);
127        let record_information = RecordSpecification::deserialize(&mut buffer);
128        Ok(TransferOwnershipPdu {
129            pdu_header,
130            originating_id,
131            receiving_id,
132            request_id,
133            required_reliability_service,
134            transfer_type,
135            transfer_entity_id,
136            record_information,
137        })
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::TransferOwnershipPdu;
144    use crate::common::{
145        pdu::Pdu,
146        pdu_header::{PduHeader, PduType, ProtocolFamily},
147    };
148    use bytes::BytesMut;
149
150    #[test]
151    fn create_header() {
152        let transfer_ownership_pdu = TransferOwnershipPdu::default();
153        let pdu_header = PduHeader::default(
154            PduType::TransferOwnership,
155            ProtocolFamily::EntityManagement,
156            448 / 8,
157        );
158
159        assert_eq!(
160            pdu_header.protocol_version,
161            transfer_ownership_pdu.pdu_header.protocol_version
162        );
163        assert_eq!(
164            pdu_header.exercise_id,
165            transfer_ownership_pdu.pdu_header.exercise_id
166        );
167        assert_eq!(
168            pdu_header.pdu_type,
169            transfer_ownership_pdu.pdu_header.pdu_type
170        );
171        assert_eq!(
172            pdu_header.protocol_family,
173            transfer_ownership_pdu.pdu_header.protocol_family
174        );
175        assert_eq!(pdu_header.length, transfer_ownership_pdu.pdu_header.length);
176        assert_eq!(
177            pdu_header.status_record,
178            transfer_ownership_pdu.pdu_header.status_record
179        );
180    }
181
182    #[test]
183    fn deserialize_header() {
184        let mut transfer_ownership_pdu = TransferOwnershipPdu::default();
185        let mut buffer = BytesMut::new();
186        transfer_ownership_pdu.serialize(&mut buffer);
187
188        let new_transfer_ownership_pdu = TransferOwnershipPdu::deserialize(buffer).unwrap();
189        assert_eq!(
190            new_transfer_ownership_pdu.pdu_header,
191            transfer_ownership_pdu.pdu_header
192        );
193    }
194}