open_dis_rust/warfare/
directed_energy_fire_pdu.rs1use bytes::{Buf, BufMut, BytesMut};
8use std::any::Any;
9
10use crate::common::{
11 dis_error::DISError,
12 entity_id::EntityId,
13 pdu::Pdu,
14 pdu_header::{PduHeader, PduType, ProtocolFamily},
15};
16
17use super::data_types::directed_energy_damage::DirectedEnergyDamage;
18
19#[derive(Clone, Debug)]
20pub struct DirectedEnergyFirePdu {
22 pub pdu_header: PduHeader,
23 pub firing_entity_id: EntityId,
24 pub target_entity_id: EntityId,
25 pub damaged_entity_id: EntityId,
26 pub padding1: u16,
27 pub padding2: u16,
28 pub number_of_damage_descriptions: u16,
29 pub damage_descriptions: Vec<DirectedEnergyDamage>,
30}
31
32impl Default for DirectedEnergyFirePdu {
33 fn default() -> Self {
44 DirectedEnergyFirePdu {
45 pdu_header: PduHeader::default(
46 PduType::DirectedEnergyFire,
47 ProtocolFamily::Warfare,
48 56,
49 ),
50 firing_entity_id: EntityId::default(1),
51 target_entity_id: EntityId::default(2),
52 damaged_entity_id: EntityId::default(3),
53 padding1: 0,
54 padding2: 0,
55 number_of_damage_descriptions: 0,
56 damage_descriptions: vec![],
57 }
58 }
59}
60
61impl Pdu for DirectedEnergyFirePdu {
62 fn serialize(&mut self, buf: &mut BytesMut) {
64 self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
65 .expect("The length of the PDU should fit in a u16.");
66 self.pdu_header.serialize(buf);
67 self.firing_entity_id.serialize(buf);
68 self.target_entity_id.serialize(buf);
69 self.damaged_entity_id.serialize(buf);
70 buf.put_u16(self.padding1);
71 buf.put_u16(self.padding2);
72 buf.put_u16(self.number_of_damage_descriptions);
73 for i in 0..self.damage_descriptions.len() {
74 self.damage_descriptions[i].serialize(buf);
75 }
76 }
77
78 fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
80 where
81 Self: Sized,
82 {
83 let pdu_header = PduHeader::deserialize(&mut buffer);
84 if pdu_header.pdu_type == PduType::DirectedEnergyFire {
85 let firing_entity_id = EntityId::deserialize(&mut buffer);
86 let target_entity_id = EntityId::deserialize(&mut buffer);
87 let damaged_entity_id = EntityId::deserialize(&mut buffer);
88 let padding1 = buffer.get_u16();
89 let padding2 = buffer.get_u16();
90 let number_of_damage_descriptions = buffer.get_u16();
91 let damage_descriptions: Vec<DirectedEnergyDamage> = vec![];
92 Ok(DirectedEnergyFirePdu {
93 pdu_header,
94 firing_entity_id,
95 target_entity_id,
96 damaged_entity_id,
97 padding1,
98 padding2,
99 number_of_damage_descriptions,
100 damage_descriptions,
101 })
102 } else {
103 Err(DISError::invalid_header(
104 format!(
105 "Expected PDU type DirectedEnergyFire, got {:?}",
106 pdu_header.pdu_type
107 ),
108 None,
109 ))
110 }
111 }
112
113 fn as_any(&self) -> &dyn Any {
115 self
116 }
117
118 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 damaged_entity_id = EntityId::deserialize(&mut buffer);
129 let padding1 = buffer.get_u16();
130 let padding2 = buffer.get_u16();
131 let number_of_damage_descriptions = buffer.get_u16();
132 let damage_descriptions: Vec<DirectedEnergyDamage> = vec![];
133 Ok(DirectedEnergyFirePdu {
134 pdu_header,
135 firing_entity_id,
136 target_entity_id,
137 damaged_entity_id,
138 padding1,
139 padding2,
140 number_of_damage_descriptions,
141 damage_descriptions,
142 })
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::DirectedEnergyFirePdu;
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 directed_energy_fire_pdu = DirectedEnergyFirePdu::default();
158 let pdu_header = PduHeader::default(
159 PduType::DirectedEnergyFire,
160 ProtocolFamily::Warfare,
161 448 / 8,
162 );
163
164 assert_eq!(
165 pdu_header.protocol_version,
166 directed_energy_fire_pdu.pdu_header.protocol_version
167 );
168 assert_eq!(
169 pdu_header.exercise_id,
170 directed_energy_fire_pdu.pdu_header.exercise_id
171 );
172 assert_eq!(
173 pdu_header.pdu_type,
174 directed_energy_fire_pdu.pdu_header.pdu_type
175 );
176 assert_eq!(
177 pdu_header.protocol_family,
178 directed_energy_fire_pdu.pdu_header.protocol_family
179 );
180 assert_eq!(
181 pdu_header.length,
182 directed_energy_fire_pdu.pdu_header.length
183 );
184 assert_eq!(
185 pdu_header.status_record,
186 directed_energy_fire_pdu.pdu_header.status_record
187 );
188 }
189
190 #[test]
191 fn cast_to_any() {
192 let directed_energy_fire_pdu = DirectedEnergyFirePdu::default();
193 let any_pdu = directed_energy_fire_pdu.as_any();
194
195 assert!(any_pdu.is::<DirectedEnergyFirePdu>());
196 }
197
198 #[test]
199 fn deserialize_header() {
200 let mut directed_energy_fire_pdu = DirectedEnergyFirePdu::default();
201 let mut buffer = BytesMut::new();
202 directed_energy_fire_pdu.serialize(&mut buffer);
203
204 let new_directed_energy_fire_pdu = DirectedEnergyFirePdu::deserialize(buffer).unwrap();
205 assert_eq!(
206 new_directed_energy_fire_pdu.pdu_header,
207 directed_energy_fire_pdu.pdu_header
208 );
209 }
210}