use std::any::Any;
use bytes::{BytesMut, BufMut, Buf};
use crate::common::{pdu_header_record::{PDUHeaderRecord, PDUType, ProtocolFamily}, entity_id_record::EntityIDRecord, pdu::PDU, dis_error::DISError};
#[derive(Copy, Clone, Debug,)]
pub struct EventReportPDU {
pub pdu_header_record: PDUHeaderRecord,
pub originating_entity_id_record: EntityIDRecord,
pub receviving_entity_id_record: EntityIDRecord,
pub event_type_field: EventType,
pub padding: u32,
pub number_of_fixed_datum_records_field: u32,
pub number_of_variable_datum_records_field: u32,
pub fixed_datum_records_field: u64,
pub variable_datum_records_field: u64,
}
impl EventReportPDU {
pub fn default() -> Self {
EventReportPDU {
pdu_header_record: PDUHeaderRecord::default(PDUType::EventReport, ProtocolFamily::SimulationManagement, 56),
originating_entity_id_record: EntityIDRecord::default(1),
receviving_entity_id_record: EntityIDRecord::default(2),
event_type_field: EventType::EntityInitialization,
padding: 0,
number_of_fixed_datum_records_field: 0,
number_of_variable_datum_records_field: 0,
fixed_datum_records_field: 0,
variable_datum_records_field: 0,
}
}
}
impl PDU for EventReportPDU {
fn serialise(&self, buf: &mut BytesMut) {
self.pdu_header_record.serialize(buf);
self.originating_entity_id_record.serialize(buf);
self.receviving_entity_id_record.serialize(buf);
buf.put_u32(self.event_type_field as u32);
buf.put_u32(self.padding);
buf.put_u32(self.number_of_fixed_datum_records_field);
buf.put_u32(self.number_of_variable_datum_records_field);
buf.put_u64(self.fixed_datum_records_field);
buf.put_u64(self.variable_datum_records_field);
}
fn deserialise(mut buffer: BytesMut) -> Result<Self, crate::common::dis_error::DISError> where Self: Sized {
let pdu_header = PDUHeaderRecord::decode(&mut buffer);
if pdu_header.pdu_type == PDUType::EventReport {
let originating_entity_id = EntityIDRecord::decode(&mut buffer);
let receviving_entity_id = EntityIDRecord::decode(&mut buffer);
let event_type = EventType::from_u32(buffer.get_u32());
let padding = buffer.get_u32();
let num_of_fixed_records = buffer.get_u32();
let num_of_variable_records = buffer.get_u32();
let mut fixed_records: u64 = 0;
for _record in 0..num_of_fixed_records as usize {
fixed_records += buffer.get_u64();
}
let mut variable_records: u64 = 0;
for _record in 0..num_of_variable_records as usize {
variable_records += buffer.get_u64();
}
return Ok(EventReportPDU {
pdu_header_record: pdu_header,
originating_entity_id_record: originating_entity_id,
receviving_entity_id_record: receviving_entity_id,
event_type_field: event_type,
padding,
number_of_fixed_datum_records_field: num_of_fixed_records,
number_of_variable_datum_records_field: num_of_variable_records,
fixed_datum_records_field: fixed_records,
variable_datum_records_field: variable_records,
})
} else {
Err(DISError::InvalidDISHeader)
}
}
fn as_any(&self) -> &dyn Any {
self
}
fn deserialise_without_header(mut buffer: BytesMut, pdu_header: PDUHeaderRecord) -> Result<Self, DISError> where Self: Sized {
let originating_entity_id = EntityIDRecord::decode(&mut buffer);
let receviving_entity_id = EntityIDRecord::decode(&mut buffer);
let event_type = EventType::from_u32(buffer.get_u32());
let padding = buffer.get_u32();
let num_of_fixed_records = buffer.get_u32();
let num_of_variable_records = buffer.get_u32();
let mut fixed_records: u64 = 0;
for _record in 0..num_of_fixed_records as usize {
fixed_records += buffer.get_u64();
}
let mut variable_records: u64 = 0;
for _record in 0..num_of_variable_records as usize {
variable_records += buffer.get_u64();
}
return Ok(EventReportPDU {
pdu_header_record: pdu_header,
originating_entity_id_record: originating_entity_id,
receviving_entity_id_record: receviving_entity_id,
event_type_field: event_type,
padding,
number_of_fixed_datum_records_field: num_of_fixed_records,
number_of_variable_datum_records_field: num_of_variable_records,
fixed_datum_records_field: fixed_records,
variable_datum_records_field: variable_records,
})
}
}
#[derive(Debug, Clone, Copy)]
pub enum EventType {
Other = 0,
Unused = 1,
IndirectOrCASFire = 10,
MinefieldEntry = 11,
MinefieldDetonantion = 12,
VehicleMasterPowerOn = 13,
VehicleMasterPowerOff = 14,
AggregateStateChangeRequest = 15,
RanOutOfAmmunition = 2,
KilledInAction = 3,
Damage = 4,
MobilityDisabled = 5,
FireDisabled = 6,
RanOutOfFuel = 7,
EntityInitialization = 8,
RequestForIndirectOrCASFire = 9,
}
impl EventType {
pub fn from_u32(data: u32) -> EventType {
match data {
0 => EventType::Other,
1 => EventType::Unused,
10 => EventType::IndirectOrCASFire,
11 => EventType::MinefieldEntry,
12 => EventType::MinefieldDetonantion,
13 => EventType::VehicleMasterPowerOn,
14 => EventType::VehicleMasterPowerOff,
15 => EventType::AggregateStateChangeRequest,
2 => EventType::RanOutOfAmmunition,
3 => EventType::KilledInAction,
4 => EventType::Damage,
5 => EventType::MobilityDisabled,
6 => EventType::FireDisabled,
7 => EventType::RanOutOfFuel,
8 => EventType::EntityInitialization,
9 => EventType::RequestForIndirectOrCASFire,
_ => EventType::Other
}
}
}
#[cfg(test)]
mod tests {
use crate::{common::pdu_header_record::{PDUHeaderRecord, PDUType, ProtocolFamily}, simulation_management::event_report_pdu::EventReportPDU, };
#[test]
fn header_creation() {
let event_report_pdu = EventReportPDU::default();
let header = PDUHeaderRecord::default(PDUType::EventReport, ProtocolFamily::SimulationManagement, 448/8);
assert_eq!(header.protocol_version, event_report_pdu.pdu_header_record.protocol_version);
assert_eq!(header.exercise_id, event_report_pdu.pdu_header_record.exercise_id);
assert_eq!(header.pdu_type, event_report_pdu.pdu_header_record.pdu_type);
assert_eq!(header.protocol_family, event_report_pdu.pdu_header_record.protocol_family);
assert_eq!(header.timestamp, event_report_pdu.pdu_header_record.timestamp);
assert_eq!(header.length, event_report_pdu.pdu_header_record.length);
assert_eq!(header.padding, event_report_pdu .pdu_header_record.padding);
}
}