open_dis_rust/entity_information/
collision_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::common::{
11    dis_error::DISError,
12    entity_id::EntityId,
13    event_id::EventId,
14    pdu::Pdu,
15    pdu_header::{PduHeader, PduType, ProtocolFamily},
16    vector3_float::Vector3Float,
17};
18
19#[derive(Clone, Debug)]
20/// Implemented according to IEEE 1278.1-2012 ยง7.2.3
21pub struct CollisionPdu {
22    pub pdu_header: PduHeader,
23    pub issuing_entity_id: EntityId,
24    pub colliding_entity_id: EntityId,
25    pub event_id: EventId,
26    pub collision_type: u8,
27    pub padding: u8,
28    pub velocity: Vector3Float,
29    pub mass: f32,
30    pub location_wrt_entity: Vector3Float,
31}
32
33impl Default for CollisionPdu {
34    fn default() -> Self {
35        CollisionPdu {
36            pdu_header: PduHeader::default(
37                PduType::Collision,
38                ProtocolFamily::EntityInformation,
39                60,
40            ),
41            issuing_entity_id: EntityId::default(1),
42            colliding_entity_id: EntityId::default(2),
43            event_id: EventId::default(1),
44            collision_type: 0,
45            padding: 0,
46            velocity: Vector3Float::default(),
47            mass: 0.0,
48            location_wrt_entity: Vector3Float::default(),
49        }
50    }
51}
52
53impl Pdu for CollisionPdu {
54    fn serialize(&mut self, buf: &mut BytesMut) {
55        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
56            .expect("The length of the PDU should fit in a u16.");
57        self.pdu_header.serialize(buf);
58        self.issuing_entity_id.serialize(buf);
59        self.colliding_entity_id.serialize(buf);
60        self.event_id.serialize(buf);
61        buf.put_u8(self.collision_type);
62        buf.put_u8(self.padding);
63        self.velocity.serialize(buf);
64        buf.put_f32(self.mass);
65        self.location_wrt_entity.serialize(buf);
66    }
67
68    fn deserialize(mut buffer: BytesMut) -> Result<CollisionPdu, DISError> {
69        let pdu_header = PduHeader::deserialize(&mut buffer);
70        if pdu_header.pdu_type == PduType::Collision {
71            let issuing_entity_id = EntityId::deserialize(&mut buffer);
72            let colliding_entity_id = EntityId::deserialize(&mut buffer);
73            let event_id = EventId::deserialize(&mut buffer);
74            let collision_type = buffer.get_u8();
75            let padding = buffer.get_u8();
76            let velocity = Vector3Float::deserialize(&mut buffer);
77            let mass = buffer.get_f32();
78            let location_wrt_entity = Vector3Float::deserialize(&mut buffer);
79            Ok(CollisionPdu {
80                pdu_header,
81                issuing_entity_id,
82                colliding_entity_id,
83                event_id,
84                collision_type,
85                padding,
86                velocity,
87                mass,
88                location_wrt_entity,
89            })
90        } else {
91            Err(DISError::invalid_header(
92                format!("Expected PDU type Collision, got {:?}", pdu_header.pdu_type),
93                None,
94            ))
95        }
96    }
97
98    fn as_any(&self) -> &dyn Any {
99        self
100    }
101
102    fn deserialize_without_header(
103        mut buffer: BytesMut,
104        pdu_header: PduHeader,
105    ) -> Result<Self, DISError>
106    where
107        Self: Sized,
108    {
109        let issuing_entity_id = EntityId::deserialize(&mut buffer);
110        let colliding_entity_id = EntityId::deserialize(&mut buffer);
111        let event_id = EventId::deserialize(&mut buffer);
112        let collision_type = buffer.get_u8();
113        let padding = buffer.get_u8();
114        let velocity = Vector3Float::deserialize(&mut buffer);
115        let mass = buffer.get_f32();
116        let location_wrt_entity = Vector3Float::deserialize(&mut buffer);
117        Ok(CollisionPdu {
118            pdu_header,
119            issuing_entity_id,
120            colliding_entity_id,
121            event_id,
122            collision_type,
123            padding,
124            velocity,
125            mass,
126            location_wrt_entity,
127        })
128    }
129}
130
131#[cfg(test)]
132mod tests {
133    use super::CollisionPdu;
134    use crate::common::{
135        pdu::Pdu,
136        pdu_header::{PduHeader, PduType, ProtocolFamily},
137    };
138    use bytes::BytesMut;
139
140    #[test]
141    fn create_header() {
142        let collision_pdu = CollisionPdu::default();
143        let header = PduHeader::default(PduType::Collision, ProtocolFamily::EntityInformation, 60);
144        assert_eq!(
145            header.protocol_version,
146            collision_pdu.pdu_header.protocol_version
147        );
148        assert_eq!(header.exercise_id, collision_pdu.pdu_header.exercise_id);
149        assert_eq!(header.pdu_type, collision_pdu.pdu_header.pdu_type);
150        assert_eq!(
151            header.protocol_family,
152            collision_pdu.pdu_header.protocol_family
153        );
154        assert_eq!(header.length, collision_pdu.pdu_header.length);
155        assert_eq!(header.status_record, collision_pdu.pdu_header.status_record);
156    }
157
158    #[test]
159    fn deserialize_header() {
160        let mut collision_pdu = CollisionPdu::default();
161        let mut buffer = BytesMut::new();
162        collision_pdu.serialize(&mut buffer);
163
164        let new_collision_pdu = CollisionPdu::deserialize(buffer).unwrap();
165        assert_eq!(new_collision_pdu.pdu_header, collision_pdu.pdu_header);
166    }
167}