1use bytes::{Buf, BufMut, BytesMut};
8use chrono::{Timelike, Utc};
9use num_derive::FromPrimitive;
10
11#[derive(Copy, Clone, Debug, Default, PartialEq)]
12pub struct PduHeader {
13 pub protocol_version: ProtocolVersion,
15 pub exercise_id: u8,
17 pub pdu_type: PduType,
19 pub protocol_family: ProtocolFamily,
21 pub timestamp: u32,
23 pub length: u16,
25 pub padding: u16,
27}
28
29impl PduHeader {
30 #[must_use]
31 pub fn new(
32 pdu_type: PduType,
33 protocol_family: ProtocolFamily,
34 exercise_id: u8,
35 length: u16,
36 ) -> Self {
37 PduHeader {
38 protocol_version: ProtocolVersion::IEEE1278_1_2012,
39 exercise_id,
40 pdu_type,
41 protocol_family,
42 timestamp: PduHeader::calculate_dis_timestamp(),
43 length,
44 padding: 0_u16,
45 }
46 }
47
48 #[must_use]
49 pub fn default(pdu_type: PduType, protocol_family: ProtocolFamily, length: u16) -> Self {
50 PduHeader {
51 protocol_version: ProtocolVersion::IEEE1278_1_2012,
52 exercise_id: 1,
53 pdu_type,
54 protocol_family,
55 timestamp: PduHeader::calculate_dis_timestamp(),
56 length,
57 padding: 0_u16,
58 }
59 }
60
61 #[must_use]
63 #[allow(
64 clippy::cast_precision_loss,
65 clippy::cast_possible_truncation,
66 clippy::cast_sign_loss
67 )]
68 pub fn calculate_dis_timestamp() -> u32 {
69 let minute_curr = u64::from((Utc::now().minute() * 60) * 1_000_000);
70 let second_curr = u64::from(Utc::now().second() * 1_000_000);
71 let nanosecond_curr = u64::from(Utc::now().nanosecond() / 1000);
72 let dis_time = (second_curr + minute_curr + nanosecond_curr) as f32 / 1.68;
73 dis_time as u32
74 }
75
76 pub fn serialize(&self, buf: &mut BytesMut) {
77 buf.put_u8(self.protocol_version as u8);
78 buf.put_u8(self.exercise_id);
79 buf.put_u8(self.pdu_type as u8);
80 buf.put_u8(self.protocol_family as u8);
81 buf.put_u32(self.timestamp);
82 buf.put_u16(self.length);
83 buf.put_u16(self.padding);
84 }
85
86 fn decode_protocol_version(data: u8) -> ProtocolVersion {
87 match data {
88 1 => ProtocolVersion::DIS_PDUv1,
89 2 => ProtocolVersion::IEEE1278_1993,
90 3 => ProtocolVersion::DIS_PDUv2_Third_Draft,
91 4 => ProtocolVersion::DIS_PDUv2_Fourth_Draft_Revised,
92 5 => ProtocolVersion::IEEE1278_1_1995,
93 6 => ProtocolVersion::IEEE1278_1A_1998,
94 7 => ProtocolVersion::IEEE1278_1_2012,
95 _ => ProtocolVersion::Other,
96 }
97 }
98
99 pub fn decode(buf: &mut BytesMut) -> PduHeader {
100 PduHeader {
101 protocol_version: PduHeader::decode_protocol_version(buf.get_u8()),
102 exercise_id: buf.get_u8(),
103 pdu_type: PduHeader::decode_pdu_type(buf.get_u8()),
104 protocol_family: PduHeader::decode_protocol_family(buf.get_u8()),
105 timestamp: buf.get_u32(),
106 length: buf.get_u16(),
107 padding: buf.get_u16(),
108 }
109 }
110
111 #[must_use]
112 pub fn decode_pdu_type(data: u8) -> PduType {
113 match data {
114 1 => PduType::EntityState,
115 2 => PduType::Fire,
116 3 => PduType::Detonation,
117 4 => PduType::Collision,
118 5 => PduType::ServiceRequest,
119 6 => PduType::ResupplyOffer,
120 7 => PduType::ResupplyReceived,
121 8 => PduType::ResupplyCancel,
122 9 => PduType::RepairComplete,
123 10 => PduType::RepairResponse,
124 11 => PduType::CreateEntity,
125 12 => PduType::RemoveEntity,
126 13 => PduType::StartResume,
127 14 => PduType::StopFreeze,
128 15 => PduType::Acknowledge,
129 16 => PduType::ActionRequest,
130 17 => PduType::ActionResponse,
131 18 => PduType::DataQuery,
132 19 => PduType::SetData,
133 20 => PduType::Data,
134 21 => PduType::EventReport,
135 22 => PduType::Comment,
136 23 => PduType::ElectromagneticEmission,
137 24 => PduType::Designator,
138 25 => PduType::Transmitter,
139 26 => PduType::Signal,
140 27 => PduType::Receiver,
141 28 => PduType::IFF,
142 29 => PduType::UnderwaterAcoustic,
143 30 => PduType::SupplementalEmission,
144 31 => PduType::IntercomSignal,
145 32 => PduType::IntercomControl,
146 33 => PduType::AggregateState,
147 34 => PduType::IsGroupOf,
148 35 => PduType::TransferOwnership,
149 36 => PduType::IsPartOf,
150 37 => PduType::MinefieldState,
151 38 => PduType::MinefieldQuery,
152 39 => PduType::MinefieldData,
153 40 => PduType::MinefieldResponseNack,
154 41 => PduType::EnvironmentalProcess,
155 42 => PduType::GriddedData,
156 43 => PduType::PointObjectState,
157 44 => PduType::LinearObjectState,
158 45 => PduType::ArealObjectState,
159 46 => PduType::TSPI,
160 47 => PduType::Appearance,
161 48 => PduType::ArticulatedParts,
162 49 => PduType::LEFire,
163 50 => PduType::LEDetonation,
164 51 => PduType::CreateEntityReliable,
165 52 => PduType::RemoveEntityReliable,
166 53 => PduType::StartResumeReliable,
167 54 => PduType::StopFreezeReliable,
168 55 => PduType::AcknowledgeReliable,
169 56 => PduType::ActionRequestReliable,
170 57 => PduType::ActionResponseReliable,
171 58 => PduType::DataQueryReliable,
172 59 => PduType::SetDataReliable,
173 60 => PduType::DataReliable,
174 61 => PduType::EventReportReliable,
175 62 => PduType::CommentReliable,
176 63 => PduType::RecordReliable,
177 64 => PduType::SetRecordReliable,
178 65 => PduType::RecordQueryReliable,
179 66 => PduType::CollisionElastic,
180 67 => PduType::EntityStateUpdate,
181 68 => PduType::DirectedEnergyFire,
182 69 => PduType::EntityDamageStatus,
183 70 => PduType::InformationOperationsAction,
184 71 => PduType::InformationOperationsReport,
185 72 => PduType::Attribute,
186 _ => PduType::Other,
187 }
188 }
189
190 #[must_use]
191 fn decode_protocol_family(data: u8) -> ProtocolFamily {
192 match data {
193 1 => ProtocolFamily::EntityInformation,
194 2 => ProtocolFamily::Warfare,
195 3 => ProtocolFamily::Logistics,
196 4 => ProtocolFamily::RadioCommunications,
197 5 => ProtocolFamily::SimulationManagement,
198 6 => ProtocolFamily::DistributedEmissionRegeneration,
199 7 => ProtocolFamily::EntityManagement,
200 8 => ProtocolFamily::Minefield,
201 9 => ProtocolFamily::SyntheticEnvironment,
202 10 => ProtocolFamily::SimulationManagementWithReliability,
203 11 => ProtocolFamily::LiveEntityInformationInteraction,
204 12 => ProtocolFamily::NonRealTime,
205 13 => ProtocolFamily::InformationOperations,
206 _ => ProtocolFamily::Other,
207 }
208 }
209}
210
211#[derive(Copy, Clone, Debug, Default, FromPrimitive, PartialEq)]
212pub enum ProtocolFamily {
213 #[default]
214 Other = 0,
215 EntityInformation = 1,
216 Warfare = 2,
217 Logistics = 3,
218 RadioCommunications = 4,
219 SimulationManagement = 5,
220 DistributedEmissionRegeneration = 6,
221 EntityManagement = 7,
222 Minefield = 8,
223 SyntheticEnvironment = 9,
224 SimulationManagementWithReliability = 10,
225 LiveEntityInformationInteraction = 11,
226 NonRealTime = 12,
227 InformationOperations = 13,
228}
229
230#[derive(Copy, Clone, Debug, Default, FromPrimitive, PartialEq)]
231#[allow(non_camel_case_types)]
232pub enum ProtocolVersion {
233 #[default]
234 Other = 0,
235 DIS_PDUv1 = 1,
236 IEEE1278_1993 = 2,
237 DIS_PDUv2_Third_Draft = 3,
238 DIS_PDUv2_Fourth_Draft_Revised = 4,
239 IEEE1278_1_1995 = 5,
240 IEEE1278_1A_1998 = 6,
241 IEEE1278_1_2012 = 7,
242}
243
244#[derive(Copy, Clone, Debug, Default, FromPrimitive, PartialEq)]
245pub enum PduType {
246 #[default]
247 Other = 0,
248 EntityState = 1,
249 Fire = 2,
250 Detonation = 3,
251 Collision = 4,
252 ServiceRequest = 5,
253 ResupplyOffer = 6,
254 ResupplyReceived = 7,
255 ResupplyCancel = 8,
256 RepairComplete = 9,
257 RepairResponse = 10,
258 CreateEntity = 11,
259 RemoveEntity = 12,
260 StartResume = 13,
261 StopFreeze = 14,
262 Acknowledge = 15,
263 ActionRequest = 16,
264 ActionResponse = 17,
265 DataQuery = 18,
266 SetData = 19,
267 Data = 20,
268 EventReport = 21,
269 Comment = 22,
270 ElectromagneticEmission = 23,
271 Designator = 24,
272 Transmitter = 25,
273 Signal = 26,
274 Receiver = 27,
275 IFF = 28,
276 UnderwaterAcoustic = 29,
277 SupplementalEmission = 30,
278 IntercomSignal = 31,
279 IntercomControl = 32,
280 AggregateState = 33,
281 IsGroupOf = 34,
282 TransferOwnership = 35,
283 IsPartOf = 36,
284 MinefieldState = 37,
285 MinefieldQuery = 38,
286 MinefieldData = 39,
287 MinefieldResponseNack = 40,
288 EnvironmentalProcess = 41,
289 GriddedData = 42,
290 PointObjectState = 43,
291 LinearObjectState = 44,
292 ArealObjectState = 45,
293 TSPI = 46,
294 Appearance = 47,
295 ArticulatedParts = 48,
296 LEFire = 49,
297 LEDetonation = 50,
298 CreateEntityReliable = 51,
299 RemoveEntityReliable = 52,
300 StartResumeReliable = 53,
301 StopFreezeReliable = 54,
302 AcknowledgeReliable = 55,
303 ActionRequestReliable = 56,
304 ActionResponseReliable = 57,
305 DataQueryReliable = 58,
306 SetDataReliable = 59,
307 DataReliable = 60,
308 EventReportReliable = 61,
309 CommentReliable = 62,
310 RecordReliable = 63,
311 SetRecordReliable = 64,
312 RecordQueryReliable = 65,
313 CollisionElastic = 66,
314 EntityStateUpdate = 67,
315 DirectedEnergyFire = 68,
316 EntityDamageStatus = 69,
317 InformationOperationsAction = 70,
318 InformationOperationsReport = 71,
319 Attribute = 72,
320}