1use crate::common::{
8 dis_error::DISError,
9 entity_type::EntityType,
10 euler_angles::EulerAngles,
11 pdu::Pdu,
12 pdu_header::{PduHeader, PduType, ProtocolFamily},
13 vector3_double::Vector3Double,
14};
15use bytes::{Buf, BufMut, BytesMut};
16use std::any::Any;
17
18use super::data_types::{minefield_identifier::MinefieldIdentifier, point::Point};
19
20#[derive(Clone, Debug)]
21pub struct MinefieldStatePdu {
23 pub pdu_header: PduHeader,
24 pub minefield_id: MinefieldIdentifier,
25 pub minefield_sequence: u16,
26 pub force_id: u8,
27 pub number_of_perimeter_points: u8,
28 pub minefield_type: EntityType,
29 pub number_of_mine_types: u16,
30 pub minefield_location: Vector3Double,
31 pub minefield_orientation: EulerAngles,
32 pub appearance: u16,
33 pub protocol_mode: u16,
34 pub perimeter_points: Vec<Point>,
35 pub mine_type: Vec<EntityType>,
36}
37
38impl Default for MinefieldStatePdu {
39 fn default() -> Self {
40 MinefieldStatePdu {
41 pdu_header: PduHeader::default(PduType::MinefieldState, ProtocolFamily::Minefield, 56),
42 minefield_id: MinefieldIdentifier::default(),
43 minefield_sequence: 0,
44 force_id: 0,
45 number_of_perimeter_points: 0,
46 minefield_type: EntityType::default(),
47 number_of_mine_types: 0,
48 minefield_location: Vector3Double::default(),
49 minefield_orientation: EulerAngles::default(),
50 appearance: 0,
51 protocol_mode: 0,
52 perimeter_points: vec![Point::default()],
53 mine_type: vec![EntityType::default()],
54 }
55 }
56}
57
58impl Pdu for MinefieldStatePdu {
59 fn serialize(&mut self, buf: &mut BytesMut) {
60 self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
61 .expect("The length of the PDU should fit in a u16.");
62 self.pdu_header.serialize(buf);
63 self.minefield_id.serialize(buf);
64 buf.put_u16(self.minefield_sequence);
65 buf.put_u8(self.force_id);
66 buf.put_u8(self.number_of_perimeter_points);
67 self.minefield_type.serialize(buf);
68 buf.put_u16(self.number_of_mine_types);
69 self.minefield_location.serialize(buf);
70 self.minefield_orientation.serialize(buf);
71 buf.put_u16(self.appearance);
72 buf.put_u16(self.protocol_mode);
73 for i in 0..self.perimeter_points.len() {
74 self.perimeter_points[i].serialize(buf);
75 }
76 for i in 0..self.mine_type.len() {
77 self.mine_type[i].serialize(buf);
78 }
79 }
80
81 fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
82 where
83 Self: Sized,
84 {
85 let pdu_header = PduHeader::deserialize(&mut buffer);
86 if pdu_header.pdu_type == PduType::MinefieldState {
87 let minefield_id = MinefieldIdentifier::deserialize(&mut buffer);
88 let minefield_sequence = buffer.get_u16();
89 let force_id = buffer.get_u8();
90 let number_of_perimeter_points = buffer.get_u8();
91 let minefield_type = EntityType::deserialize(&mut buffer);
92 let number_of_mine_types = buffer.get_u16();
93 let minefield_location = Vector3Double::deserialize(&mut buffer);
94 let minefield_orientation = EulerAngles::deserialize(&mut buffer);
95 let appearance = buffer.get_u16();
96 let protocol_mode = buffer.get_u16();
97 let mut perimeter_points: Vec<Point> = vec![];
98 for _i in 0..number_of_perimeter_points {
99 perimeter_points.push(Point::deserialize(&mut buffer));
100 }
101 let mut mine_type: Vec<EntityType> = vec![];
102 for _i in 0..number_of_mine_types {
103 mine_type.push(EntityType::deserialize(&mut buffer));
104 }
105
106 Ok(MinefieldStatePdu {
107 pdu_header,
108 minefield_id,
109 minefield_sequence,
110 force_id,
111 number_of_perimeter_points,
112 minefield_type,
113 number_of_mine_types,
114 minefield_location,
115 minefield_orientation,
116 appearance,
117 protocol_mode,
118 perimeter_points,
119 mine_type,
120 })
121 } else {
122 Err(DISError::invalid_header(
123 format!(
124 "Expected PDU type MinefieldState, got {:?}",
125 pdu_header.pdu_type
126 ),
127 None,
128 ))
129 }
130 }
131
132 fn as_any(&self) -> &dyn Any {
133 self
134 }
135
136 fn deserialize_without_header(
137 mut buffer: BytesMut,
138 pdu_header: PduHeader,
139 ) -> Result<Self, DISError>
140 where
141 Self: Sized,
142 {
143 let minefield_id = MinefieldIdentifier::deserialize(&mut buffer);
144 let minefield_sequence = buffer.get_u16();
145 let force_id = buffer.get_u8();
146 let number_of_perimeter_points = buffer.get_u8();
147 let minefield_type = EntityType::deserialize(&mut buffer);
148 let number_of_mine_types = buffer.get_u16();
149 let minefield_location = Vector3Double::deserialize(&mut buffer);
150 let minefield_orientation = EulerAngles::deserialize(&mut buffer);
151 let appearance = buffer.get_u16();
152 let protocol_mode = buffer.get_u16();
153 let mut perimeter_points: Vec<Point> = vec![];
154 for _i in 0..number_of_perimeter_points {
155 perimeter_points.push(Point::deserialize(&mut buffer));
156 }
157 let mut mine_type: Vec<EntityType> = vec![];
158 for _i in 0..number_of_mine_types {
159 mine_type.push(EntityType::deserialize(&mut buffer));
160 }
161
162 Ok(MinefieldStatePdu {
163 pdu_header,
164 minefield_id,
165 minefield_sequence,
166 force_id,
167 number_of_perimeter_points,
168 minefield_type,
169 number_of_mine_types,
170 minefield_location,
171 minefield_orientation,
172 appearance,
173 protocol_mode,
174 perimeter_points,
175 mine_type,
176 })
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::MinefieldStatePdu;
183 use crate::common::pdu_header::{PduHeader, PduType, ProtocolFamily};
184
185 #[test]
186 fn create_header() {
187 let minefield_state_pdu = MinefieldStatePdu::default();
188 let pdu_header =
189 PduHeader::default(PduType::MinefieldState, ProtocolFamily::Minefield, 448 / 8);
190
191 assert_eq!(
192 pdu_header.protocol_version,
193 minefield_state_pdu.pdu_header.protocol_version
194 );
195 assert_eq!(
196 pdu_header.exercise_id,
197 minefield_state_pdu.pdu_header.exercise_id
198 );
199 assert_eq!(pdu_header.pdu_type, minefield_state_pdu.pdu_header.pdu_type);
200 assert_eq!(
201 pdu_header.protocol_family,
202 minefield_state_pdu.pdu_header.protocol_family
203 );
204 assert_eq!(pdu_header.length, minefield_state_pdu.pdu_header.length);
205 assert_eq!(
206 pdu_header.status_record,
207 minefield_state_pdu.pdu_header.status_record
208 );
209 }
210}