open_dis_rust/distributed_emissions/
underwater_acoustic_pdu.rs1use bytes::{Buf, BufMut, BytesMut};
8use std::any::Any;
9
10use crate::common::{
11 dis_error::DISError,
12 entity_id::EntityId,
13 enums::{UAPassiveParameterIndex, UAStateChangeUpdateIndicator},
14 event_id::EventId,
15 pdu::Pdu,
16 pdu_header::{PduHeader, PduType, ProtocolFamily},
17};
18
19use super::data_types::{
20 acoustic_emitter_system::AcousticEmitterSystem, apa_data::ApaData, shaft_rpms::ShaftRPMs,
21};
22
23#[derive(Clone, Debug)]
24pub struct UnderwaterAcousticPdu {
26 pub pdu_header: PduHeader,
27 pub emitting_entity_id: EntityId,
28 pub event_id: EventId,
29 pub state_change_indicator: UAStateChangeUpdateIndicator,
30 pub pad: u8,
31 pub passive_parameter_index: UAPassiveParameterIndex,
32 pub propulsion_plant_configuration: u8,
33 pub number_of_shafts: u8,
34 pub number_of_apas: u8,
35 pub number_of_ua_emitter_systems: u8,
36 pub shaft_rpms: Vec<ShaftRPMs>,
37 pub apa_data: Vec<ApaData>,
38 pub emitter_systems: Vec<AcousticEmitterSystem>,
39}
40
41impl Default for UnderwaterAcousticPdu {
42 fn default() -> Self {
53 UnderwaterAcousticPdu {
54 pdu_header: PduHeader::default(
55 PduType::UnderwaterAcoustic,
56 ProtocolFamily::DistributedEmissionRegeneration,
57 56,
58 ),
59 emitting_entity_id: EntityId::default(1),
60 event_id: EventId::default(1),
61 state_change_indicator: UAStateChangeUpdateIndicator::default(),
62 pad: 0,
63 passive_parameter_index: UAPassiveParameterIndex::default(),
64 propulsion_plant_configuration: 0,
65 number_of_shafts: 0,
66 number_of_apas: 0,
67 number_of_ua_emitter_systems: 0,
68 shaft_rpms: vec![],
69 apa_data: vec![],
70 emitter_systems: vec![],
71 }
72 }
73}
74
75impl Pdu for UnderwaterAcousticPdu {
76 fn serialize(&mut self, buf: &mut BytesMut) {
78 self.pdu_header.length = u16::try_from(std::mem::size_of_val(self))
79 .expect("The length of the PDU should fit in a u16.");
80 self.pdu_header.serialize(buf);
81 self.emitting_entity_id.serialize(buf);
82 self.event_id.serialize(buf);
83 buf.put_u8(self.state_change_indicator as u8);
84 buf.put_u8(self.pad);
85 buf.put_u16(self.passive_parameter_index as u16);
86 buf.put_u8(self.propulsion_plant_configuration);
87 buf.put_u8(self.number_of_shafts);
88 buf.put_u8(self.number_of_apas);
89 buf.put_u8(self.number_of_ua_emitter_systems);
90 for i in 0..self.shaft_rpms.len() {
91 self.shaft_rpms[i].serialize(buf);
92 }
93 for i in 0..self.apa_data.len() {
94 self.apa_data[i].serialize(buf);
95 }
96 for i in 0..self.emitter_systems.len() {
97 self.emitter_systems[i].serialize(buf);
98 }
99 }
100
101 fn deserialize(mut buffer: BytesMut) -> Result<Self, DISError>
103 where
104 Self: Sized,
105 {
106 let pdu_header = PduHeader::deserialize(&mut buffer);
107 if pdu_header.pdu_type == PduType::UnderwaterAcoustic {
108 let emitting_entity_id = EntityId::deserialize(&mut buffer);
109 let event_id = EventId::deserialize(&mut buffer);
110 let state_change_indicator = UAStateChangeUpdateIndicator::deserialize(&mut buffer);
111 let pad = buffer.get_u8();
112 let passive_parameter_index = UAPassiveParameterIndex::deserialize(&mut buffer);
113 let propulsion_plant_configuration = buffer.get_u8();
114 let number_of_shafts = buffer.get_u8();
115 let number_of_apas = buffer.get_u8();
116 let number_of_ua_emitter_systems = buffer.get_u8();
117 let mut shaft_rpms: Vec<ShaftRPMs> = vec![];
118 for _i in 0..number_of_shafts {
119 shaft_rpms.push(ShaftRPMs::deserialize(&mut buffer));
120 }
121 let mut apa_data: Vec<ApaData> = vec![];
122 for _i in 0..number_of_apas {
123 apa_data.push(ApaData::deserialize(&mut buffer));
124 }
125 let mut emitter_systems: Vec<AcousticEmitterSystem> = vec![];
126 for _i in 0..number_of_ua_emitter_systems {
127 emitter_systems.push(AcousticEmitterSystem::deserialize(&mut buffer));
128 }
129 Ok(UnderwaterAcousticPdu {
130 pdu_header,
131 emitting_entity_id,
132 event_id,
133 state_change_indicator,
134 pad,
135 passive_parameter_index,
136 propulsion_plant_configuration,
137 number_of_shafts,
138 number_of_apas,
139 number_of_ua_emitter_systems,
140 shaft_rpms,
141 apa_data,
142 emitter_systems,
143 })
144 } else {
145 Err(DISError::invalid_header(
146 format!(
147 "Expected PDU type UnderwaterAcoustic, got {:?}",
148 pdu_header.pdu_type
149 ),
150 None,
151 ))
152 }
153 }
154
155 fn as_any(&self) -> &dyn Any {
157 self
158 }
159
160 fn deserialize_without_header(
162 mut buffer: BytesMut,
163 pdu_header: PduHeader,
164 ) -> Result<Self, DISError>
165 where
166 Self: Sized,
167 {
168 let emitting_entity_id = EntityId::deserialize(&mut buffer);
169 let event_id = EventId::deserialize(&mut buffer);
170 let state_change_indicator = UAStateChangeUpdateIndicator::deserialize(&mut buffer);
171 let pad = buffer.get_u8();
172 let passive_parameter_index = UAPassiveParameterIndex::deserialize(&mut buffer);
173 let propulsion_plant_configuration = buffer.get_u8();
174 let number_of_shafts = buffer.get_u8();
175 let number_of_apas = buffer.get_u8();
176 let number_of_ua_emitter_systems = buffer.get_u8();
177 let mut shaft_rpms: Vec<ShaftRPMs> = vec![];
178 for _i in 0..number_of_shafts {
179 shaft_rpms.push(ShaftRPMs::deserialize(&mut buffer));
180 }
181 let mut apa_data: Vec<ApaData> = vec![];
182 for _i in 0..number_of_apas {
183 apa_data.push(ApaData::deserialize(&mut buffer));
184 }
185 let mut emitter_systems: Vec<AcousticEmitterSystem> = vec![];
186 for _i in 0..number_of_ua_emitter_systems {
187 emitter_systems.push(AcousticEmitterSystem::deserialize(&mut buffer));
188 }
189 Ok(UnderwaterAcousticPdu {
190 pdu_header,
191 emitting_entity_id,
192 event_id,
193 state_change_indicator,
194 pad,
195 passive_parameter_index,
196 propulsion_plant_configuration,
197 number_of_shafts,
198 number_of_apas,
199 number_of_ua_emitter_systems,
200 shaft_rpms,
201 apa_data,
202 emitter_systems,
203 })
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::UnderwaterAcousticPdu;
210 use crate::common::{
211 pdu::Pdu,
212 pdu_header::{PduHeader, PduType, ProtocolFamily},
213 };
214 use bytes::BytesMut;
215
216 #[test]
217 fn create_header() {
218 let supplemental_emission_pdu = UnderwaterAcousticPdu::default();
219 let pdu_header = PduHeader::default(
220 PduType::UnderwaterAcoustic,
221 ProtocolFamily::DistributedEmissionRegeneration,
222 448 / 8,
223 );
224
225 assert_eq!(
226 pdu_header.protocol_version,
227 supplemental_emission_pdu.pdu_header.protocol_version
228 );
229 assert_eq!(
230 pdu_header.exercise_id,
231 supplemental_emission_pdu.pdu_header.exercise_id
232 );
233 assert_eq!(
234 pdu_header.pdu_type,
235 supplemental_emission_pdu.pdu_header.pdu_type
236 );
237 assert_eq!(
238 pdu_header.protocol_family,
239 supplemental_emission_pdu.pdu_header.protocol_family
240 );
241 assert_eq!(
242 pdu_header.length,
243 supplemental_emission_pdu.pdu_header.length
244 );
245 assert_eq!(
246 pdu_header.status_record,
247 supplemental_emission_pdu.pdu_header.status_record
248 );
249 }
250
251 #[test]
252 fn cast_to_any() {
253 let udnerwater_acoustic_pdu = UnderwaterAcousticPdu::default();
254 let any_pdu = udnerwater_acoustic_pdu.as_any();
255
256 assert!(any_pdu.is::<UnderwaterAcousticPdu>());
257 }
258
259 #[test]
260 fn deserialize_header() {
261 let mut supplemental_emission_pdu = UnderwaterAcousticPdu::default();
262 let mut buffer = BytesMut::new();
263 supplemental_emission_pdu.serialize(&mut buffer);
264
265 let new_supplemental_emission_pdu = UnderwaterAcousticPdu::deserialize(buffer).unwrap();
266 assert_eq!(
267 new_supplemental_emission_pdu.pdu_header,
268 supplemental_emission_pdu.pdu_header
269 );
270 }
271}