open_dis_rust/warfare/
fire_pdu.rs1use 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_double::Vector3Double,
17 vector3_float::Vector3Float,
18};
19
20use super::data_types::munition_descriptor::MunitionDescriptor;
21
22#[derive(Clone, Debug)]
23pub struct FirePdu {
25 pub pdu_header: PduHeader,
26 pub firing_entity_id: EntityId,
27 pub target_entity_id: EntityId,
28 pub munition_expendable_id: EntityId,
29 pub event_id: EventId,
30 pub fire_mission_index: u32,
31 pub location_in_world_coordinates: Vector3Double,
32 pub descriptor: MunitionDescriptor,
33 pub velocity: Vector3Float,
34 pub range: f32,
35}
36
37impl Default for FirePdu {
38 fn default() -> Self {
49 FirePdu {
50 pdu_header: PduHeader::default(PduType::Fire, ProtocolFamily::Warfare, 56),
51 firing_entity_id: EntityId::default(1),
52 target_entity_id: EntityId::default(2),
53 munition_expendable_id: EntityId::default(3),
54 event_id: EventId::default(1),
55 fire_mission_index: 0,
56 location_in_world_coordinates: Vector3Double::default(),
57 descriptor: MunitionDescriptor::default(),
58 velocity: Vector3Float::default(),
59 range: 0.0,
60 }
61 }
62}
63
64impl Pdu for FirePdu {
65 fn serialize(&mut self, buf: &mut BytesMut) {
66 self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
67 .expect("The length of the PDU should fit in a u16.");
68 self.pdu_header.serialize(buf);
69 self.firing_entity_id.serialize(buf);
70 self.target_entity_id.serialize(buf);
71 self.munition_expendable_id.serialize(buf);
72 self.event_id.serialize(buf);
73 buf.put_u32(self.fire_mission_index);
74 self.location_in_world_coordinates.serialize(buf);
75 self.descriptor.serialize(buf);
76 self.velocity.serialize(buf);
77 buf.put_f32(self.range);
78 }
79
80 fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
81 where
82 Self: Sized,
83 {
84 let pdu_header = PduHeader::deserialize(&mut buffer);
85 if pdu_header.pdu_type == PduType::Fire {
86 let firing_entity_id = EntityId::deserialize(&mut buffer);
87 let target_entity_id = EntityId::deserialize(&mut buffer);
88 let munition_expendable_id = EntityId::deserialize(&mut buffer);
89 let event_id = EventId::deserialize(&mut buffer);
90 let fire_mission_index = buffer.get_u32();
91 let location_in_world_coordinates = Vector3Double::deserialize(&mut buffer);
92 let descriptor = MunitionDescriptor::deserialize(&mut buffer);
93 let velocity = Vector3Float::deserialize(&mut buffer);
94 let range = buffer.get_f32();
95 Ok(FirePdu {
96 pdu_header,
97 firing_entity_id,
98 target_entity_id,
99 munition_expendable_id,
100 event_id,
101 fire_mission_index,
102 location_in_world_coordinates,
103 descriptor,
104 velocity,
105 range,
106 })
107 } else {
108 Err(DISError::invalid_header(
109 format!("Expected PDU type Fire, got {:?}", pdu_header.pdu_type),
110 None,
111 ))
112 }
113 }
114
115 fn as_any(&self) -> &dyn Any {
116 self
117 }
118
119 fn deserialize_without_header(
120 mut buffer: BytesMut,
121 pdu_header: PduHeader,
122 ) -> Result<Self, DISError>
123 where
124 Self: Sized,
125 {
126 let firing_entity_id = EntityId::deserialize(&mut buffer);
127 let target_entity_id = EntityId::deserialize(&mut buffer);
128 let munition_expendable_id = EntityId::deserialize(&mut buffer);
129 let event_id = EventId::deserialize(&mut buffer);
130 let fire_mission_index = buffer.get_u32();
131 let location_in_world_coordinates = Vector3Double::deserialize(&mut buffer);
132 let descriptor = MunitionDescriptor::deserialize(&mut buffer);
133 let velocity = Vector3Float::deserialize(&mut buffer);
134 let range = buffer.get_f32();
135 Ok(FirePdu {
136 pdu_header,
137 firing_entity_id,
138 target_entity_id,
139 munition_expendable_id,
140 event_id,
141 fire_mission_index,
142 location_in_world_coordinates,
143 descriptor,
144 velocity,
145 range,
146 })
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::FirePdu;
153 use crate::common::{
154 pdu::Pdu,
155 pdu_header::{PduHeader, PduType, ProtocolFamily},
156 };
157 use bytes::BytesMut;
158
159 #[test]
160 fn create_header() {
161 let fire_pdu = FirePdu::default();
162 let pdu_header = PduHeader::default(PduType::Fire, ProtocolFamily::Warfare, 448 / 8);
163
164 assert_eq!(
165 pdu_header.protocol_version,
166 fire_pdu.pdu_header.protocol_version
167 );
168 assert_eq!(pdu_header.exercise_id, fire_pdu.pdu_header.exercise_id);
169 assert_eq!(pdu_header.pdu_type, fire_pdu.pdu_header.pdu_type);
170 assert_eq!(
171 pdu_header.protocol_family,
172 fire_pdu.pdu_header.protocol_family
173 );
174 assert_eq!(pdu_header.length, fire_pdu.pdu_header.length);
175 assert_eq!(pdu_header.status_record, fire_pdu.pdu_header.status_record);
176 }
177
178 #[test]
179 fn deserialize_header() {
180 let mut fire_pdu = FirePdu::default();
181 let mut buffer = BytesMut::new();
182 fire_pdu.serialize(&mut buffer);
183
184 let new_fire_pdu = FirePdu::deserialize(buffer).unwrap();
185 assert_eq!(new_fire_pdu.pdu_header, fire_pdu.pdu_header);
186 }
187}