open_dis_rust/minefield/
minefield_data_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    entity_type::EntityType,
11    pdu::Pdu,
12    pdu_header::{PduHeader, PduType, ProtocolFamily},
13    vector3_float::Vector3Float,
14};
15use bytes::{Buf, BufMut, BytesMut};
16use std::any::Any;
17
18#[derive(Clone, Debug)]
19/// Implemented according to IEEE 1278.1-2012 ยง7.9.4
20pub struct MinefieldDataPdu {
21    pub pdu_header: PduHeader,
22    pub minefield_id: EntityId,
23    pub requesting_entity_id: EntityId,
24    pub minefield_sequence_number: u16,
25    pub request_id: u8,
26    pub pdu_sequence_number: u8,
27    pub number_of_pdus: u8,
28    pub number_of_mines_in_this_pdu: u8,
29    pub number_of_sensor_types: u8,
30    pub pad2: u8,
31    pub data_filter: u32,
32    pub mine_type: EntityType,
33    pub sensor_types: Vec<u16>,
34    pub pad3: u8,
35    pub mine_location: Vec<Vector3Float>,
36}
37
38impl Default for MinefieldDataPdu {
39    fn default() -> Self {
40        MinefieldDataPdu {
41            pdu_header: PduHeader::default(PduType::MinefieldData, ProtocolFamily::Minefield, 56),
42            minefield_id: EntityId::default(1),
43            requesting_entity_id: EntityId::default(2),
44            minefield_sequence_number: 0,
45            request_id: 0,
46            pdu_sequence_number: 0,
47            number_of_pdus: 0,
48            number_of_mines_in_this_pdu: 0,
49            number_of_sensor_types: 0,
50            pad2: 0,
51            data_filter: 0,
52            mine_type: EntityType::default(),
53            sensor_types: vec![0],
54            pad3: 0,
55            mine_location: vec![Vector3Float::new(0.0, 0.0, 0.0)],
56        }
57    }
58}
59
60impl Pdu for MinefieldDataPdu {
61    fn serialize(&mut self, buf: &mut BytesMut) {
62        self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
63            .expect("The length of the PDU should fit in a u16.");
64        self.pdu_header.serialize(buf);
65        self.minefield_id.serialize(buf);
66        self.requesting_entity_id.serialize(buf);
67        buf.put_u16(self.minefield_sequence_number);
68        buf.put_u8(self.request_id);
69        buf.put_u8(self.pdu_sequence_number);
70        buf.put_u8(self.number_of_pdus);
71        buf.put_u8(self.number_of_mines_in_this_pdu);
72        buf.put_u8(self.number_of_sensor_types);
73        buf.put_u8(self.pad2);
74        buf.put_u32(self.data_filter);
75        self.mine_type.serialize(buf);
76        for i in 0..self.sensor_types.len() {
77            buf.put_u16(self.sensor_types[i]);
78        }
79        buf.put_u8(self.pad3);
80        for i in 0..self.mine_location.len() {
81            self.mine_location[i].serialize(buf);
82        }
83    }
84
85    fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
86    where
87        Self: Sized,
88    {
89        let pdu_header = PduHeader::deserialize(&mut buffer);
90        if pdu_header.pdu_type == PduType::MinefieldData {
91            let minefield_id = EntityId::deserialize(&mut buffer);
92            let requesting_entity_id = EntityId::deserialize(&mut buffer);
93            let minefield_sequence_number = buffer.get_u16();
94            let request_id = buffer.get_u8();
95            let pdu_sequence_number = buffer.get_u8();
96            let number_of_pdus = buffer.get_u8();
97            let number_of_mines_in_this_pdu = buffer.get_u8();
98            let number_of_sensor_types = buffer.get_u8();
99            let pad2 = buffer.get_u8();
100            let data_filter = buffer.get_u32();
101            let mine_type = EntityType::deserialize(&mut buffer);
102            let mut sensor_types: Vec<u16> = vec![];
103            for _i in 0..number_of_sensor_types as usize {
104                sensor_types.push(buffer.get_u16());
105            }
106            let pad3 = buffer.get_u8();
107            let mut mine_location: Vec<Vector3Float> = vec![];
108            for _i in 0..number_of_mines_in_this_pdu as usize {
109                mine_location.push(Vector3Float::deserialize(&mut buffer));
110            }
111
112            Ok(MinefieldDataPdu {
113                pdu_header,
114                minefield_id,
115                requesting_entity_id,
116                minefield_sequence_number,
117                request_id,
118                pdu_sequence_number,
119                number_of_pdus,
120                number_of_mines_in_this_pdu,
121                number_of_sensor_types,
122                pad2,
123                data_filter,
124                mine_type,
125                sensor_types,
126                pad3,
127                mine_location,
128            })
129        } else {
130            Err(DISError::invalid_header(
131                format!(
132                    "Expected PDU type MinefieldData, got {:?}",
133                    pdu_header.pdu_type
134                ),
135                None,
136            ))
137        }
138    }
139
140    fn as_any(&self) -> &dyn Any {
141        self
142    }
143
144    fn deserialize_without_header(
145        mut buffer: BytesMut,
146        pdu_header: PduHeader,
147    ) -> Result<Self, DISError>
148    where
149        Self: Sized,
150    {
151        let minefield_id = EntityId::deserialize(&mut buffer);
152        let requesting_entity_id = EntityId::deserialize(&mut buffer);
153        let minefield_sequence_number = buffer.get_u16();
154        let request_id = buffer.get_u8();
155        let pdu_sequence_number = buffer.get_u8();
156        let number_of_pdus = buffer.get_u8();
157        let number_of_mines_in_this_pdu = buffer.get_u8();
158        let number_of_sensor_types = buffer.get_u8();
159        let pad2 = buffer.get_u8();
160        let data_filter = buffer.get_u32();
161        let mine_type = EntityType::deserialize(&mut buffer);
162        let mut sensor_types: Vec<u16> = vec![];
163        for _i in 0..number_of_sensor_types as usize {
164            sensor_types.push(buffer.get_u16());
165        }
166        let pad3 = buffer.get_u8();
167        let mut mine_location: Vec<Vector3Float> = vec![];
168        for _i in 0..number_of_mines_in_this_pdu as usize {
169            mine_location.push(Vector3Float::deserialize(&mut buffer));
170        }
171
172        Ok(MinefieldDataPdu {
173            pdu_header,
174            minefield_id,
175            requesting_entity_id,
176            minefield_sequence_number,
177            request_id,
178            pdu_sequence_number,
179            number_of_pdus,
180            number_of_mines_in_this_pdu,
181            number_of_sensor_types,
182            pad2,
183            data_filter,
184            mine_type,
185            sensor_types,
186            pad3,
187            mine_location,
188        })
189    }
190}
191
192#[cfg(test)]
193mod tests {
194    use super::MinefieldDataPdu;
195    use crate::common::pdu_header::{PduHeader, PduType, ProtocolFamily};
196
197    #[test]
198    fn create_header() {
199        let minefield_data_pdu = MinefieldDataPdu::default();
200        let pdu_header =
201            PduHeader::default(PduType::MinefieldData, ProtocolFamily::Minefield, 448 / 8);
202
203        assert_eq!(
204            pdu_header.protocol_version,
205            minefield_data_pdu.pdu_header.protocol_version
206        );
207        assert_eq!(
208            pdu_header.exercise_id,
209            minefield_data_pdu.pdu_header.exercise_id
210        );
211        assert_eq!(pdu_header.pdu_type, minefield_data_pdu.pdu_header.pdu_type);
212        assert_eq!(
213            pdu_header.protocol_family,
214            minefield_data_pdu.pdu_header.protocol_family
215        );
216        assert_eq!(pdu_header.length, minefield_data_pdu.pdu_header.length);
217        assert_eq!(
218            pdu_header.status_record,
219            minefield_data_pdu.pdu_header.status_record
220        );
221    }
222}