open_dis_rust/synthetic_environment/
areal_object_state_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    entity_type::EntityType,
14    enums::ObjectStateAppearanceGeneral,
15    pdu::Pdu,
16    pdu_header::{PduHeader, PduType, ProtocolFamily},
17    simulation_address::SimulationAddress,
18    vector3_double::Vector3Double,
19};
20
21#[derive(Clone, Debug)]
22/// Implemented according to IEEE 1278.1-2012 ยง7.10.6
23pub struct ArealObjectStatePdu {
24    pub pdu_header: PduHeader,
25    pub object_id: EntityId,
26    pub referenced_object_id: EntityId,
27    pub update_number: u16,
28    pub force_id: u8,
29    pub modifications: u8,
30    pub object_type: EntityType,
31    pub specific_object_appearance: u32, // TODO(@anyone) Implement Specific Object Appearance
32    pub general_object_appearance: ObjectStateAppearanceGeneral,
33    pub number_of_points: u16,
34    pub requester_id: SimulationAddress,
35    pub receiving_id: SimulationAddress,
36    pub object_location: Vec<Vector3Double>,
37}
38
39impl Default for ArealObjectStatePdu {
40    /// Creates a default Areal Object State PDU with arbitrary environmental process ID
41    ///
42    /// # Examples
43    ///
44    /// Initializing an Areal Object State PDU:
45    /// ```
46    /// use open_dis_rust::synthetic_environment::areal_object_state_pdu::ArealObjectStatePdu;
47    /// let areal_object_state_pdu = ArealObjectStatePdu::default();
48    /// ```
49    ///
50    fn default() -> Self {
51        ArealObjectStatePdu {
52            pdu_header: PduHeader::default(
53                PduType::ArealObjectState,
54                ProtocolFamily::SyntheticEnvironment,
55                56,
56            ),
57            object_id: EntityId::default(1),
58            referenced_object_id: EntityId::default(2),
59            update_number: 0,
60            force_id: 0,
61            modifications: 0,
62            object_type: EntityType::default(),
63            specific_object_appearance: 0,
64            general_object_appearance: ObjectStateAppearanceGeneral::default(),
65            number_of_points: 0,
66            requester_id: SimulationAddress::default(),
67            receiving_id: SimulationAddress::default(),
68            object_location: vec![],
69        }
70    }
71}
72
73impl Pdu for ArealObjectStatePdu {
74    fn serialize(&mut self, buf: &mut BytesMut) {
75        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
76            .expect("The length of the PDU should fit in a u16.");
77        self.pdu_header.serialize(buf);
78        self.object_id.serialize(buf);
79        self.referenced_object_id.serialize(buf);
80        buf.put_u16(self.update_number);
81        buf.put_u8(self.force_id);
82        buf.put_u8(self.modifications);
83        self.object_type.serialize(buf);
84        buf.put_u32(self.specific_object_appearance);
85        buf.put_u16(self.general_object_appearance.as_u16());
86        buf.put_u16(self.number_of_points);
87        self.requester_id.serialize(buf);
88        self.receiving_id.serialize(buf);
89        for i in 0..self.object_location.len() {
90            self.object_location[i].serialize(buf);
91        }
92    }
93
94    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
95    where
96        Self: Sized,
97    {
98        let pdu_header = PduHeader::deserialize(&mut buffer);
99        if pdu_header.pdu_type == PduType::ArealObjectState {
100            let object_id = EntityId::deserialize(&mut buffer);
101            let referenced_object_id = EntityId::deserialize(&mut buffer);
102            let update_number = buffer.get_u16();
103            let force_id = buffer.get_u8();
104            let modifications = buffer.get_u8();
105            let object_type = EntityType::deserialize(&mut buffer);
106            let specific_object_appearance = buffer.get_u32();
107            let general_object_appearance =
108                ObjectStateAppearanceGeneral::from_u16(buffer.get_u16()).unwrap();
109            let number_of_points = buffer.get_u16();
110            let requester_id = SimulationAddress::deserialize(&mut buffer);
111            let receiving_id = SimulationAddress::deserialize(&mut buffer);
112            let mut object_location: Vec<Vector3Double> = vec![];
113            for _i in 0..number_of_points {
114                object_location.push(Vector3Double::deserialize(&mut buffer));
115            }
116            Ok(ArealObjectStatePdu {
117                pdu_header,
118                object_id,
119                referenced_object_id,
120                update_number,
121                force_id,
122                modifications,
123                object_type,
124                specific_object_appearance,
125                general_object_appearance,
126                number_of_points,
127                requester_id,
128                receiving_id,
129                object_location,
130            })
131        } else {
132            Err(DISError::invalid_header(
133                format!(
134                    "Expected PDU type ArealObjectState, got {:?}",
135                    pdu_header.pdu_type
136                ),
137                None,
138            ))
139        }
140    }
141
142    fn as_any(&self) -> &dyn Any {
143        self
144    }
145
146    fn deserialize_without_header(
147        mut buffer: BytesMut,
148        pdu_header: PduHeader,
149    ) -> Result<Self, DISError>
150    where
151        Self: Sized,
152    {
153        let object_id = EntityId::deserialize(&mut buffer);
154        let referenced_object_id = EntityId::deserialize(&mut buffer);
155        let update_number = buffer.get_u16();
156        let force_id = buffer.get_u8();
157        let modifications = buffer.get_u8();
158        let object_type = EntityType::deserialize(&mut buffer);
159        let specific_object_appearance = buffer.get_u32();
160        let general_object_appearance =
161            ObjectStateAppearanceGeneral::from_u16(buffer.get_u16()).unwrap();
162        let number_of_points = buffer.get_u16();
163        let requester_id = SimulationAddress::deserialize(&mut buffer);
164        let receiving_id = SimulationAddress::deserialize(&mut buffer);
165        let mut object_location: Vec<Vector3Double> = vec![];
166        for _i in 0..number_of_points {
167            object_location.push(Vector3Double::deserialize(&mut buffer));
168        }
169        Ok(ArealObjectStatePdu {
170            pdu_header,
171            object_id,
172            referenced_object_id,
173            update_number,
174            force_id,
175            modifications,
176            object_type,
177            specific_object_appearance,
178            general_object_appearance,
179            number_of_points,
180            requester_id,
181            receiving_id,
182            object_location,
183        })
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use super::ArealObjectStatePdu;
190    use crate::common::{
191        pdu::Pdu,
192        pdu_header::{PduHeader, PduType, ProtocolFamily},
193    };
194    use bytes::BytesMut;
195
196    #[test]
197    fn create_header() {
198        let areal_object_state_pdu = ArealObjectStatePdu::default();
199        let pdu_header = PduHeader::default(
200            PduType::ArealObjectState,
201            ProtocolFamily::SyntheticEnvironment,
202            448 / 8,
203        );
204
205        assert_eq!(
206            pdu_header.protocol_version,
207            areal_object_state_pdu.pdu_header.protocol_version
208        );
209        assert_eq!(
210            pdu_header.exercise_id,
211            areal_object_state_pdu.pdu_header.exercise_id
212        );
213        assert_eq!(
214            pdu_header.pdu_type,
215            areal_object_state_pdu.pdu_header.pdu_type
216        );
217        assert_eq!(
218            pdu_header.protocol_family,
219            areal_object_state_pdu.pdu_header.protocol_family
220        );
221        assert_eq!(pdu_header.length, areal_object_state_pdu.pdu_header.length);
222        assert_eq!(
223            pdu_header.status_record,
224            areal_object_state_pdu.pdu_header.status_record
225        );
226    }
227
228    #[test]
229    fn deserialize_header() {
230        let mut areal_object_state_pdu = ArealObjectStatePdu::default();
231        let mut buffer = BytesMut::new();
232        areal_object_state_pdu.serialize(&mut buffer);
233
234        let new_areal_object_state_pdu = ArealObjectStatePdu::deserialize(buffer).unwrap();
235        assert_eq!(
236            new_areal_object_state_pdu.pdu_header,
237            areal_object_state_pdu.pdu_header
238        );
239    }
240}