open_dis_rust/entity_information/
entity_state_update_pdu.rs

1//     open-dis-rust - Rust implementation of the IEEE-1278.1 Distributed Interactive Simulation
2//                     (DIS) application protocol v6 and v7
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::{
11    common::{
12        dis_error::DISError,
13        entity_id::EntityId,
14        euler_angles::EulerAngles,
15        linear_velocity::LinearVelocity,
16        pdu::Pdu,
17        pdu_header::{PduHeader, PduType, ProtocolFamily},
18        world_coordinate::WorldCoordinate,
19    },
20    warfare::data_types::variable_parameter::VariableParameter,
21};
22
23#[derive(Clone, Debug)]
24/// Implemented according to IEEE 1278.1-2012 ยง7.2.5
25pub struct EntityStateUpdatePdu {
26    pub pdu_header: PduHeader,
27    pub entity_id: EntityId,
28    pub padding: u8,
29    pub number_of_variable_parameters: u8,
30    pub entity_linear_velocity: LinearVelocity,
31    pub entity_location: WorldCoordinate,
32    pub entity_orientation: EulerAngles,
33    pub entity_appearance: u32,
34    pub variable_parameter_records: Vec<VariableParameter>,
35}
36
37impl Default for EntityStateUpdatePdu {
38    fn default() -> Self {
39        EntityStateUpdatePdu {
40            pdu_header: PduHeader::default(
41                PduType::EntityStateUpdate,
42                ProtocolFamily::EntityInformation,
43                864 / 8,
44            ),
45            entity_id: EntityId::default(1),
46            padding: 0,
47            number_of_variable_parameters: 0,
48            entity_linear_velocity: LinearVelocity::default(),
49            entity_location: WorldCoordinate::default(),
50            entity_orientation: EulerAngles::default(),
51            entity_appearance: 0,
52            variable_parameter_records: vec![],
53        }
54    }
55}
56
57impl Pdu for EntityStateUpdatePdu {
58    fn serialize(&mut self, buf: &mut BytesMut) {
59        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
60            .expect("The length of the PDU should fit in a u16.");
61        self.pdu_header.serialize(buf);
62        self.entity_id.serialize(buf);
63        buf.put_u8(self.padding);
64        buf.put_u8(self.number_of_variable_parameters);
65        self.entity_linear_velocity.serialize(buf);
66        self.entity_location.serialize(buf);
67        self.entity_orientation.serialize(buf);
68        buf.put_u32(self.entity_appearance);
69        for i in 0..self.variable_parameter_records.len() {
70            self.variable_parameter_records[i].serialize(buf);
71        }
72    }
73
74    fn deserialize(mut buffer: BytesMut) -> Result<EntityStateUpdatePdu, DISError> {
75        let pdu_header = PduHeader::deserialize(&mut buffer);
76        if pdu_header.pdu_type == PduType::EntityStateUpdate {
77            let entity_id = EntityId::deserialize(&mut buffer);
78            let padding = buffer.get_u8();
79            let number_of_variable_parameters = buffer.get_u8();
80            let entity_linear_velocity = LinearVelocity::deserialize(&mut buffer);
81            let entity_location = WorldCoordinate::deserialize(&mut buffer);
82            let entity_orientation = EulerAngles::deserialize(&mut buffer);
83            let entity_appearance = buffer.get_u32();
84            let mut variable_parameter_records: Vec<VariableParameter> = vec![];
85            for _i in 0..number_of_variable_parameters {
86                variable_parameter_records.push(VariableParameter::deserialize(&mut buffer));
87            }
88            Ok(EntityStateUpdatePdu {
89                pdu_header,
90                entity_id,
91                padding,
92                number_of_variable_parameters,
93                entity_linear_velocity,
94                entity_location,
95                entity_orientation,
96                entity_appearance,
97                variable_parameter_records,
98            })
99        } else {
100            Err(DISError::invalid_header(
101                format!(
102                    "Expected PDU type EntityStateUpdate, 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 entity_id = EntityId::deserialize(&mut buffer);
122        let padding = buffer.get_u8();
123        let number_of_variable_parameters = buffer.get_u8();
124        let entity_linear_velocity = LinearVelocity::deserialize(&mut buffer);
125        let entity_location = WorldCoordinate::deserialize(&mut buffer);
126        let entity_orientation = EulerAngles::deserialize(&mut buffer);
127        let entity_appearance = buffer.get_u32();
128        let mut variable_parameter_records: Vec<VariableParameter> = vec![];
129        for _i in 0..number_of_variable_parameters {
130            variable_parameter_records.push(VariableParameter::deserialize(&mut buffer));
131        }
132        Ok(EntityStateUpdatePdu {
133            pdu_header,
134            entity_id,
135            padding,
136            number_of_variable_parameters,
137            entity_linear_velocity,
138            entity_location,
139            entity_orientation,
140            entity_appearance,
141            variable_parameter_records,
142        })
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::EntityStateUpdatePdu;
149    use crate::common::{
150        pdu::Pdu,
151        pdu_header::{PduHeader, PduType, ProtocolFamily},
152    };
153    use bytes::BytesMut;
154
155    #[test]
156    fn create_header() {
157        let entity_state_update_pdu = EntityStateUpdatePdu::default();
158        let header = PduHeader::default(
159            PduType::EntityStateUpdate,
160            ProtocolFamily::EntityInformation,
161            864 / 8,
162        );
163        assert_eq!(
164            header.protocol_version,
165            entity_state_update_pdu.pdu_header.protocol_version
166        );
167        assert_eq!(
168            header.exercise_id,
169            entity_state_update_pdu.pdu_header.exercise_id
170        );
171        assert_eq!(header.pdu_type, entity_state_update_pdu.pdu_header.pdu_type);
172        assert_eq!(
173            header.protocol_family,
174            entity_state_update_pdu.pdu_header.protocol_family
175        );
176        assert_eq!(header.length, entity_state_update_pdu.pdu_header.length);
177        assert_eq!(
178            header.status_record,
179            entity_state_update_pdu.pdu_header.status_record
180        );
181    }
182
183    #[test]
184    fn deserialize_header() {
185        let mut entity_state_update_pdu = EntityStateUpdatePdu::default();
186        let mut buffer = BytesMut::new();
187        entity_state_update_pdu.serialize(&mut buffer);
188
189        let new_entity_state_update_pdu = EntityStateUpdatePdu::deserialize(buffer).unwrap();
190        assert_eq!(
191            new_entity_state_update_pdu.pdu_header,
192            entity_state_update_pdu.pdu_header
193        );
194    }
195}