use std::any::{Any};
use crate::common::{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};
use bytes::{BytesMut, BufMut, Buf};
use super::burst_descriptor_record::BurstDescriptorRecord;
#[derive(Copy, Clone, Debug)]
pub struct FirePDU {
pub pdu_header_record: PDUHeaderRecord,
pub firing_entity_id_record: EntityIDRecord,
pub target_entity_id_record: EntityIDRecord,
pub munition_id_record: EntityIDRecord,
pub event_id_record: EventIDRecord,
pub fire_mission_index_field: u32,
pub location_in_world_record: WorldCoordinateRecord,
pub burst_descriptor_record: BurstDescriptorRecord,
pub velocity_record: VelocityVectorRecord,
pub range_field: f32
}
impl FirePDU {
pub fn default() -> Self {
FirePDU {
pdu_header_record: PDUHeaderRecord::default(PDUType::Fire, ProtocolFamily::Warfare, 96),
firing_entity_id_record: EntityIDRecord::default(1),
target_entity_id_record: EntityIDRecord::default(1),
munition_id_record: EntityIDRecord::default(1),
event_id_record: EventIDRecord::default(1),
fire_mission_index_field: 0,
location_in_world_record: WorldCoordinateRecord::new(0.0, 0.0, 0.0),
burst_descriptor_record: BurstDescriptorRecord::default(),
velocity_record: VelocityVectorRecord::new(0.0, 0.0, 0.0),
range_field: 0.0
}
}
}
impl PDU for FirePDU {
fn serialise(&self, buf: &mut BytesMut) {
self.pdu_header_record.serialize(buf);
self.firing_entity_id_record.serialize(buf);
self.target_entity_id_record.serialize(buf);
self.munition_id_record.serialize(buf);
self.event_id_record.serialize(buf);
buf.put_u32(self.fire_mission_index_field);
self.location_in_world_record.serialize(buf);
self.burst_descriptor_record.serialize(buf);
self.velocity_record.serialize(buf);
buf.put_f32(self.range_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::Fire {
let firing_entity_id = EntityIDRecord::decode(&mut buffer);
let target_entity_id = EntityIDRecord::decode(&mut buffer);
let munition_entity_id = EntityIDRecord::decode(&mut buffer);
let event_id = EventIDRecord::decode(&mut buffer);
let fire_mission = buffer.get_u32();
let location = WorldCoordinateRecord::decode(&mut buffer);
let burst_descriptor = BurstDescriptorRecord::decode(&mut buffer);
let velocity = VelocityVectorRecord::decode(&mut buffer);
let range = buffer.get_f32();
return Ok(FirePDU {
pdu_header_record: pdu_header,
firing_entity_id_record: firing_entity_id,
target_entity_id_record: target_entity_id,
munition_id_record: munition_entity_id,
event_id_record: event_id,
fire_mission_index_field: fire_mission,
location_in_world_record: location,
burst_descriptor_record: burst_descriptor,
velocity_record: velocity,
range_field: range,
})
} 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 firing_entity_id = EntityIDRecord::decode(&mut buffer);
let target_entity_id = EntityIDRecord::decode(&mut buffer);
let munition_entity_id = EntityIDRecord::decode(&mut buffer);
let event_id = EventIDRecord::decode(&mut buffer);
let fire_mission = buffer.get_u32();
let location = WorldCoordinateRecord::decode(&mut buffer);
let burst_descriptor = BurstDescriptorRecord::decode(&mut buffer);
let velocity = VelocityVectorRecord::decode(&mut buffer);
let range = buffer.get_f32();
return Ok(FirePDU {
pdu_header_record: pdu_header,
firing_entity_id_record: firing_entity_id,
target_entity_id_record: target_entity_id,
munition_id_record: munition_entity_id,
event_id_record: event_id,
fire_mission_index_field: fire_mission,
location_in_world_record: location,
burst_descriptor_record: burst_descriptor,
velocity_record: velocity,
range_field: range,
})
}
}
#[cfg(test)]
mod tests {
use bytes::BytesMut;
use crate::{common::{pdu_header_record::{PDUHeaderRecord, PDUType, ProtocolFamily}, pdu::PDU}, warfare::fire_pdu::FirePDU};
#[test]
fn header_creation() {
let firing_pdu = FirePDU::default();
let header = PDUHeaderRecord::default(PDUType::Fire, ProtocolFamily::Warfare, 768/8);
assert_eq!(header.protocol_version, firing_pdu.pdu_header_record.protocol_version);
assert_eq!(header.exercise_id, firing_pdu.pdu_header_record.exercise_id);
assert_eq!(header.pdu_type, firing_pdu.pdu_header_record.pdu_type);
assert_eq!(header.protocol_family, firing_pdu.pdu_header_record.protocol_family);
assert_eq!(header.timestamp, firing_pdu.pdu_header_record.timestamp);
assert_eq!(header.length, firing_pdu.pdu_header_record.length);
assert_eq!(header.padding, firing_pdu.pdu_header_record.padding);
}
#[test]
fn header_deserialise() {
let fire_pdu = FirePDU::default();
let mut buffer = BytesMut::new();
fire_pdu.serialise(&mut buffer);
let new_fire_pdu = FirePDU::deserialise(buffer).unwrap();
assert_eq!(new_fire_pdu.pdu_header_record, fire_pdu.pdu_header_record);
}
}