1use std::any::Any;
10
11use bytes::{BytesMut, BufMut, Buf};
12
13use crate::common::{entity_coordinate_vector_record::EntityCoordinateVectorRecord, entity_id_record::EntityIDRecord, event_id_record::EventIDRecord, pdu::PDU, pdu_header_record::{PDUHeaderRecord, PDUType, ProtocolFamily}, velocity_vector_record::VelocityVectorRecord, world_coordinate_record::WorldCoordinateRecord, dis_error::DISError};
14
15use super::burst_descriptor_record::BurstDescriptorRecord;
16
17#[derive(Copy, Clone, Debug,)]
18pub struct DetonationPDU {
20 pub pdu_header_record: PDUHeaderRecord,
21 pub firing_entity_id_record: EntityIDRecord,
22 pub target_entity_id_record: EntityIDRecord,
23 pub munition_id_record: EntityIDRecord,
24 pub event_id_record: EventIDRecord,
25 pub velocity_record: VelocityVectorRecord,
26 pub location_in_world_record: WorldCoordinateRecord,
27 pub burst_descriptor_record: BurstDescriptorRecord,
28 pub location_in_entity_coordinates_record: EntityCoordinateVectorRecord,
29 pub detonation_result_field: DetonationResult,
30 pub number_of_articulation_parameters_field: u8,
31 pub padding: u16,
32 pub articulation_parameter_record: f32 }
35
36impl DetonationPDU {
37 pub fn default() -> Self {
56 DetonationPDU {
57 pdu_header_record: PDUHeaderRecord::default(PDUType::Detonation, ProtocolFamily::Warfare, 768/8), firing_entity_id_record: EntityIDRecord::default(1),
59 target_entity_id_record: EntityIDRecord::default(2),
60 munition_id_record: EntityIDRecord::default(3),
61 event_id_record: EventIDRecord::default(1),
62 location_in_world_record: WorldCoordinateRecord::new(0.0, 0.0, 0.0),
63 burst_descriptor_record: BurstDescriptorRecord::default(),
64 velocity_record: VelocityVectorRecord::new(570.0, 0.0, 0.0),
65 location_in_entity_coordinates_record: EntityCoordinateVectorRecord::new(0.0, 0.0, 0.0),
66 detonation_result_field: DetonationResult::AirBurst,
67 number_of_articulation_parameters_field:0,
68 padding: 0,
69 articulation_parameter_record: 0.0
70 }
71 }
72}
73
74impl PDU for DetonationPDU {
75 fn serialise(&self, buf: &mut BytesMut) {
78 self.pdu_header_record.serialize(buf);
79 self.firing_entity_id_record.serialize(buf);
80 self.target_entity_id_record.serialize(buf);
81 self.munition_id_record.serialize(buf);
82 self.event_id_record.serialize(buf);
83 self.velocity_record.serialize(buf);
84 self.location_in_world_record.serialize(buf);
85 self.burst_descriptor_record.serialize(buf);
86 self.location_in_entity_coordinates_record.serialize(buf);
87 buf.put_u8(self.detonation_result_field as u8);
88 buf.put_u8(self.number_of_articulation_parameters_field);
89 buf.put_u16(self.padding);
90 }
91
92 fn deserialise(mut buffer: BytesMut) -> Result<Self, crate::common::dis_error::DISError> where Self: Sized {
93 let pdu_header = PDUHeaderRecord::decode(&mut buffer);
94 if pdu_header.pdu_type == PDUType::Detonation {
95 let firing_entity_id = EntityIDRecord::decode(&mut buffer);
96 let target_entity_id = EntityIDRecord::decode(&mut buffer);
97 let munition_entity_id = EntityIDRecord::decode(&mut buffer);
98 let event_id = EventIDRecord::decode(&mut buffer);
99 let velocity = VelocityVectorRecord::decode(&mut buffer);
100 let location = WorldCoordinateRecord::decode(&mut buffer);
101 let burst_descriptor = BurstDescriptorRecord::decode(&mut buffer);
102 let location_in_entity_coordinates = EntityCoordinateVectorRecord::decode(&mut buffer);
103 let detonation_result = DetonationResult::from_u8(buffer.get_u8());
104 let num_articulation_params = buffer.get_u8();
105 let padding = buffer.get_u16();
106 return Ok(DetonationPDU {
107 pdu_header_record: pdu_header,
108 firing_entity_id_record: firing_entity_id,
109 target_entity_id_record: target_entity_id,
110 munition_id_record: munition_entity_id,
111 event_id_record: event_id,
112 velocity_record: velocity,
113 location_in_world_record: location,
114 burst_descriptor_record: burst_descriptor,
115 location_in_entity_coordinates_record: location_in_entity_coordinates,
116 detonation_result_field: detonation_result,
117 number_of_articulation_parameters_field: num_articulation_params,
118 padding: padding,
119 articulation_parameter_record: 0.0,
120 })
121 } else {
122 Err(DISError::InvalidDISHeader)
123 }
124 }
125
126 fn as_any(&self) -> &dyn Any {
127 self
128 }
129
130 fn deserialise_without_header(mut buffer: BytesMut, pdu_header: PDUHeaderRecord) -> Result<Self, DISError> where Self: Sized {
131 let firing_entity_id = EntityIDRecord::decode(&mut buffer);
132 let target_entity_id = EntityIDRecord::decode(&mut buffer);
133 let munition_entity_id = EntityIDRecord::decode(&mut buffer);
134 let event_id = EventIDRecord::decode(&mut buffer);
135 let velocity = VelocityVectorRecord::decode(&mut buffer);
136 let location = WorldCoordinateRecord::decode(&mut buffer);
137 let burst_descriptor = BurstDescriptorRecord::decode(&mut buffer);
138 let location_in_entity_coordinates = EntityCoordinateVectorRecord::decode(&mut buffer);
139 let detonation_result = DetonationResult::from_u8(buffer.get_u8());
140 let num_articulation_params = buffer.get_u8();
141 let padding = buffer.get_u16();
142 return Ok(DetonationPDU {
143 pdu_header_record: pdu_header,
144 firing_entity_id_record: firing_entity_id,
145 target_entity_id_record: target_entity_id,
146 munition_id_record: munition_entity_id,
147 event_id_record: event_id,
148 velocity_record: velocity,
149 location_in_world_record: location,
150 burst_descriptor_record: burst_descriptor,
151 location_in_entity_coordinates_record: location_in_entity_coordinates,
152 detonation_result_field: detonation_result,
153 number_of_articulation_parameters_field: num_articulation_params,
154 padding: padding,
155 articulation_parameter_record: 0.0,
156 })
157 }
158}
159
160#[derive(Debug, Clone, Copy)]
161pub enum DetonationResult {
164 Other = 0,
165 EntityImpact = 1,
166 ArmourPiercingHit = 10,
167 SmallDirtBlast = 11,
168 MediumDirtBlast = 12,
169 LargeDirtBlast = 13,
170 SmallWaterBlast = 14,
171 MediumWaterBlast = 15,
172 LargeWaterBlast = 16,
173 AirHit = 17,
174 SmallBuildingHit = 18,
175 MediumBuildingHit = 19,
176 EntityProximateDetonation = 2,
177 LargeBuildingHit = 20,
178 MineClearingLineCharge = 21,
179 EnvironmentalObjectImpact = 22,
180 EnvironmentalObjectProximateDetonation = 23,
181 WaterImpact = 24,
182 AirBurst = 25,
183 GroundImpact = 3,
184 GroundImpactDetonation = 4,
185 Detonation = 5,
186 None = 6,
187 SmallHighExplosiveHit = 7,
188 MediumHighExplosiveHit = 8,
189 LargeHighExplosiveHit = 9
190}
191
192impl DetonationResult {
193 pub fn from_u8(value: u8) -> DetonationResult {
194 match value {
195 0 => DetonationResult::Other,
196 1 => DetonationResult::EntityImpact,
197 2 => DetonationResult::EntityProximateDetonation,
198 3 => DetonationResult::GroundImpact,
199 4 => DetonationResult::GroundImpactDetonation,
200 5 => DetonationResult::Detonation,
201 6 => DetonationResult::None,
202 7 => DetonationResult::SmallHighExplosiveHit,
203 8 => DetonationResult::MediumHighExplosiveHit,
204 9 => DetonationResult::LargeHighExplosiveHit,
205 10 => DetonationResult::ArmourPiercingHit,
206 11 => DetonationResult::SmallDirtBlast,
207 12 => DetonationResult::MediumDirtBlast,
208 13 => DetonationResult::LargeDirtBlast,
209 14 => DetonationResult::SmallWaterBlast,
210 15 => DetonationResult::MediumWaterBlast,
211 16 => DetonationResult::LargeWaterBlast,
212 17 => DetonationResult::AirHit,
213 18 => DetonationResult::SmallBuildingHit,
214 19 => DetonationResult::MediumBuildingHit,
215 20 => DetonationResult::LargeBuildingHit,
216 21 => DetonationResult::MineClearingLineCharge,
217 22 => DetonationResult::EnvironmentalObjectImpact,
218 23 => DetonationResult::EntityProximateDetonation,
219 24 => DetonationResult::WaterImpact,
220 25 => DetonationResult::AirBurst,
221 _ => DetonationResult::Other
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use crate::{common::pdu_header_record::{PDUHeaderRecord, PDUType, ProtocolFamily}, warfare::detonation_pdu::DetonationPDU};
229
230 #[test]
231 fn header_creation() {
232 let detonation_pdu = DetonationPDU::default();
233 let header = PDUHeaderRecord::default(PDUType::Detonation, ProtocolFamily::Warfare, 768/8);
234 assert_eq!(header.protocol_version, detonation_pdu.pdu_header_record.protocol_version);
235 assert_eq!(header.exercise_id, detonation_pdu.pdu_header_record.exercise_id);
236 assert_eq!(header.pdu_type, detonation_pdu.pdu_header_record.pdu_type);
237 assert_eq!(header.protocol_family, detonation_pdu.pdu_header_record.protocol_family);
238 assert_eq!(header.timestamp, detonation_pdu.pdu_header_record.timestamp);
239 assert_eq!(header.length, detonation_pdu.pdu_header_record.length);
240 assert_eq!(header.padding, detonation_pdu .pdu_header_record.padding);
241 }
242}