open_dis_rust/simulation_management/
event_report_pdu.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2023 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7use crate::common::{
8    dis_error::DISError,
9    entity_id::EntityId,
10    enums::EventType,
11    pdu::Pdu,
12    pdu_header::{PduHeader, PduType, ProtocolFamily},
13};
14use bytes::{Buf, BufMut, BytesMut};
15use std::any::Any;
16
17#[derive(Copy, Clone, Debug)]
18/// Implemented according to IEEE 1278.1-2012 ยง7.5.12
19pub struct EventReportPdu {
20    pub pdu_header: PduHeader,
21    pub originating_entity_id: EntityId,
22    pub receiving_entity_id: EntityId,
23    pub event_type: EventType,
24    pub padding: u32,
25    pub number_of_fixed_datum_records: u32,
26    pub number_of_variable_datum_records: u32,
27    pub fixed_datum_records: u64,
28    pub variable_datum_records: u64,
29}
30
31impl Default for EventReportPdu {
32    fn default() -> Self {
33        EventReportPdu {
34            pdu_header: PduHeader::default(
35                PduType::EventReport,
36                ProtocolFamily::SimulationManagement,
37                56,
38            ),
39            originating_entity_id: EntityId::default(1),
40            receiving_entity_id: EntityId::default(2),
41            event_type: EventType::Other,
42            padding: 0,
43            number_of_fixed_datum_records: 0,
44            number_of_variable_datum_records: 0,
45            fixed_datum_records: 0,
46            variable_datum_records: 0,
47        }
48    }
49}
50
51impl Pdu for EventReportPdu {
52    fn serialize(&mut self, buf: &mut BytesMut) {
53        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
54            .expect("The length of the PDU should fit in a u16.");
55        self.pdu_header.serialize(buf);
56        self.originating_entity_id.serialize(buf);
57        self.receiving_entity_id.serialize(buf);
58        buf.put_u32(self.event_type as u32);
59        buf.put_u32(self.padding);
60        buf.put_u32(self.number_of_fixed_datum_records);
61        buf.put_u32(self.number_of_variable_datum_records);
62        buf.put_u64(self.fixed_datum_records);
63        buf.put_u64(self.variable_datum_records);
64    }
65
66    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
67    where
68        Self: Sized,
69    {
70        let pdu_header = PduHeader::deserialize(&mut buffer);
71        if pdu_header.pdu_type == PduType::EventReport {
72            let originating_entity_id = EntityId::deserialize(&mut buffer);
73            let receiving_entity_id = EntityId::deserialize(&mut buffer);
74            let event_type = EventType::deserialize(&mut buffer);
75            let padding = buffer.get_u32();
76            let number_of_fixed_datum_records = buffer.get_u32();
77            let number_of_variable_datum_records = buffer.get_u32();
78            let mut fixed_datum_records: u64 = 0;
79            for _record in 0..number_of_fixed_datum_records as usize {
80                fixed_datum_records += buffer.get_u64();
81            }
82            let mut variable_datum_records: u64 = 0;
83            for _record in 0..number_of_variable_datum_records as usize {
84                variable_datum_records += buffer.get_u64();
85            }
86
87            Ok(EventReportPdu {
88                pdu_header,
89                originating_entity_id,
90                receiving_entity_id,
91                event_type,
92                padding,
93                number_of_fixed_datum_records,
94                number_of_variable_datum_records,
95                fixed_datum_records,
96                variable_datum_records,
97            })
98        } else {
99            Err(DISError::invalid_header(
100                format!(
101                    "Expected PDU type EventReport, got {:?}",
102                    pdu_header.pdu_type
103                ),
104                None,
105            ))
106        }
107    }
108
109    fn as_any(&self) -> &dyn Any {
110        self
111    }
112
113    fn deserialize_without_header(
114        mut buffer: BytesMut,
115        pdu_header: PduHeader,
116    ) -> Result<Self, DISError>
117    where
118        Self: Sized,
119    {
120        let originating_entity_id = EntityId::deserialize(&mut buffer);
121        let receiving_entity_id = EntityId::deserialize(&mut buffer);
122        let event_type = EventType::deserialize(&mut buffer);
123        let padding = buffer.get_u32();
124        let number_of_fixed_datum_records = buffer.get_u32();
125        let number_of_variable_datum_records = buffer.get_u32();
126        let mut fixed_datum_records: u64 = 0;
127        for _record in 0..number_of_fixed_datum_records as usize {
128            fixed_datum_records += buffer.get_u64();
129        }
130        let mut variable_datum_records: u64 = 0;
131        for _record in 0..number_of_variable_datum_records as usize {
132            variable_datum_records += buffer.get_u64();
133        }
134
135        Ok(EventReportPdu {
136            pdu_header,
137            originating_entity_id,
138            receiving_entity_id,
139            event_type,
140            padding,
141            number_of_fixed_datum_records,
142            number_of_variable_datum_records,
143            fixed_datum_records,
144            variable_datum_records,
145        })
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::EventReportPdu;
152    use crate::common::{
153        pdu::Pdu,
154        pdu_header::{PduHeader, PduType, ProtocolFamily},
155    };
156    use bytes::BytesMut;
157
158    #[test]
159    fn create_header() {
160        let event_report_pdu = EventReportPdu::default();
161        let pdu_header = PduHeader::default(
162            PduType::EventReport,
163            ProtocolFamily::SimulationManagement,
164            448 / 8,
165        );
166
167        assert_eq!(
168            pdu_header.protocol_version,
169            event_report_pdu.pdu_header.protocol_version
170        );
171        assert_eq!(
172            pdu_header.exercise_id,
173            event_report_pdu.pdu_header.exercise_id
174        );
175        assert_eq!(pdu_header.pdu_type, event_report_pdu.pdu_header.pdu_type);
176        assert_eq!(
177            pdu_header.protocol_family,
178            event_report_pdu.pdu_header.protocol_family
179        );
180        assert_eq!(pdu_header.length, event_report_pdu.pdu_header.length);
181        assert_eq!(
182            pdu_header.status_record,
183            event_report_pdu.pdu_header.status_record
184        );
185    }
186
187    #[test]
188    fn deserialize_header() {
189        let mut event_report_pdu = EventReportPdu::default();
190        let mut buffer = BytesMut::new();
191        event_report_pdu.serialize(&mut buffer);
192
193        let new_event_report_pdu = EventReportPdu::deserialize(buffer).unwrap();
194        assert_eq!(new_event_report_pdu.pdu_header, event_report_pdu.pdu_header);
195    }
196}