1use 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)]
19pub 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}