dis_rs/common/electromagnetic_emission/
writer.rs

1use crate::common::electromagnetic_emission::model::{
2    Beam, ElectromagneticEmission, EmitterSystem, FundamentalParameterData, JammingTechnique,
3    TrackJam,
4};
5use crate::common::{Serialize, SerializePdu, SupportedVersion};
6use bytes::{BufMut, BytesMut};
7
8impl SerializePdu for ElectromagneticEmission {
9    fn serialize_pdu(&self, _version: SupportedVersion, buf: &mut BytesMut) -> u16 {
10        let entity_bytes = self.emitting_entity_id.serialize(buf);
11        let event_bytes = self.event_id.serialize(buf);
12        buf.put_u8(self.state_update_indicator.into());
13        buf.put_u8(self.emitter_systems.len() as u8);
14        buf.put_u16(0u16);
15        let systems_bytes = self
16            .emitter_systems
17            .iter()
18            .map(|system| system.serialize(buf))
19            .sum::<u16>();
20
21        entity_bytes + event_bytes + 4 + systems_bytes
22    }
23}
24
25impl Serialize for EmitterSystem {
26    fn serialize(&self, buf: &mut BytesMut) -> u16 {
27        let system_length_in_words = self.system_data_length_bytes() / 4;
28        buf.put_u8(system_length_in_words as u8);
29        buf.put_u8(self.beams.len() as u8);
30        buf.put_u16(0u16);
31        buf.put_u16(self.name.into());
32        buf.put_u8(self.function.into());
33        buf.put_u8(self.number);
34        let location_bytes = self.location.serialize(buf);
35
36        let beams_bytes = self
37            .beams
38            .iter()
39            .map(|beam| beam.serialize(buf))
40            .sum::<u16>();
41
42        8 + location_bytes + beams_bytes
43    }
44}
45
46impl Serialize for Beam {
47    fn serialize(&self, buf: &mut BytesMut) -> u16 {
48        let beam_length_in_words = self.beam_data_length_bytes() / 4;
49        buf.put_u8(beam_length_in_words as u8);
50        buf.put_u8(self.number);
51        buf.put_u16(self.parameter_index);
52        let parameter_data_bytes = self.parameter_data.serialize(buf);
53        let beam_data_bytes = self.beam_data.serialize(buf);
54        buf.put_u8(self.beam_function.into());
55        buf.put_u8(self.track_jam_data.len() as u8);
56        buf.put_u8(self.high_density_track_jam.into());
57        buf.put_u8(self.beam_status.into());
58        let technique_bytes = self.jamming_technique.serialize(buf);
59
60        let tracks_bytes = self
61            .track_jam_data
62            .iter()
63            .map(|tracks| tracks.serialize(buf))
64            .sum::<u16>();
65
66        8 + parameter_data_bytes + beam_data_bytes + technique_bytes + tracks_bytes
67    }
68}
69
70impl Serialize for FundamentalParameterData {
71    fn serialize(&self, buf: &mut BytesMut) -> u16 {
72        buf.put_f32(self.frequency);
73        buf.put_f32(self.frequency_range);
74        buf.put_f32(self.effective_power);
75        buf.put_f32(self.pulse_repetition_frequency);
76        buf.put_f32(self.pulse_width);
77
78        20
79    }
80}
81
82impl Serialize for JammingTechnique {
83    fn serialize(&self, buf: &mut BytesMut) -> u16 {
84        buf.put_u8(self.kind);
85        buf.put_u8(self.category);
86        buf.put_u8(self.subcategory);
87        buf.put_u8(self.specific);
88
89        4
90    }
91}
92
93impl Serialize for TrackJam {
94    fn serialize(&self, buf: &mut BytesMut) -> u16 {
95        let entity_bytes = self.entity_id.serialize(buf);
96        buf.put_u8(self.emitter);
97        buf.put_u8(self.beam);
98
99        entity_bytes + 2
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use crate::common::electromagnetic_emission::model::{
106        Beam, ElectromagneticEmission, EmitterSystem, FundamentalParameterData, TrackJam,
107    };
108    use crate::common::model::{
109        BeamData, EntityId, EventId, Pdu, PduHeader, SimulationAddress, VectorF32,
110    };
111    use crate::common::BodyInfo;
112    use crate::enumerations::{
113        ElectromagneticEmissionBeamFunction, EmitterName, EmitterSystemFunction,
114        HighDensityTrackJam,
115    };
116    use bytes::BytesMut;
117
118    #[test]
119    #[allow(clippy::too_many_lines)]
120    fn write_pdu_emission_with_tracks() {
121        let body = ElectromagneticEmission::builder()
122            .with_emitting_entity_id(EntityId::new(500, 11111, 62))
123            .with_event_id(EventId::new(SimulationAddress::new(500, 11111), 577))
124            .with_emitter_system(
125                EmitterSystem::new()
126                    .with_name(EmitterName::Unnamed_32175)
127                    .with_function(EmitterSystemFunction::Multifunction_1)
128                    .with_number(1)
129                    .with_location(VectorF32::new(0f32, 0f32, 5f32))
130                    .with_beam(
131                        Beam::new()
132                            .with_number(2)
133                            .with_parameter_index(122)
134                            .with_parameter_data(
135                                FundamentalParameterData::new()
136                                    .with_frequency(6_000_000_000f32)
137                                    .with_frequency_range(0f32)
138                                    .with_effective_power(f32::from_be_bytes([
139                                        0x42, 0xf0, 0x00, 0x00,
140                                    ]))
141                                    .with_pulse_repetition_frequency(0f32)
142                                    .with_pulse_width(0f32),
143                            )
144                            .with_beam_data(
145                                BeamData::new()
146                                    .with_azimuth_center(f32::from_be_bytes([
147                                        0x3e, 0x05, 0xd5, 0xff,
148                                    ]))
149                                    .with_azimuth_sweep(f32::from_be_bytes([
150                                        0x3c, 0x0e, 0xfa, 0x35,
151                                    ]))
152                                    .with_elevation_center(f32::from_be_bytes([
153                                        0x3f, 0x30, 0x95, 0x12,
154                                    ]))
155                                    .with_elevation_sweep(f32::from_be_bytes([
156                                        0x3c, 0x0e, 0xfa, 0x35,
157                                    ]))
158                                    .with_sweep_sync(0f32),
159                            )
160                            .with_beam_function(ElectromagneticEmissionBeamFunction::Illumination)
161                            .with_high_density_track_jam(HighDensityTrackJam::NotSelected)
162                            .with_track_jam(
163                                TrackJam::new()
164                                    .with_beam(0)
165                                    .with_emitter(0)
166                                    .with_entity_id(EntityId::new(500, 11111, 71)),
167                            ),
168                    )
169                    .with_beam(
170                        Beam::new()
171                            .with_number(1)
172                            .with_parameter_index(100)
173                            .with_parameter_data(
174                                FundamentalParameterData::new()
175                                    .with_frequency(6_000_000_000f32)
176                                    .with_frequency_range(0f32)
177                                    .with_effective_power(f32::from_be_bytes([
178                                        0x42, 0xf0, 0x00, 0x00,
179                                    ]))
180                                    .with_pulse_repetition_frequency(f32::from_be_bytes([
181                                        0x45, 0x9c, 0x40, 0x00,
182                                    ]))
183                                    .with_pulse_width(f32::from_be_bytes([0x42, 0x48, 0x00, 0x00])),
184                            )
185                            .with_beam_data(
186                                BeamData::new()
187                                    .with_azimuth_center(f32::from_be_bytes([
188                                        0x3e, 0x05, 0xd6, 0x14,
189                                    ]))
190                                    .with_azimuth_sweep(f32::from_be_bytes([
191                                        0x3c, 0x0e, 0xfa, 0x35,
192                                    ]))
193                                    .with_elevation_center(f32::from_be_bytes([
194                                        0x3f, 0x30, 0x95, 0x54,
195                                    ]))
196                                    .with_elevation_sweep(f32::from_be_bytes([
197                                        0x3c, 0x0e, 0xfa, 0x35,
198                                    ]))
199                                    .with_sweep_sync(0f32),
200                            )
201                            .with_beam_function(ElectromagneticEmissionBeamFunction::Tracking)
202                            .with_high_density_track_jam(HighDensityTrackJam::NotSelected)
203                            .with_track_jam(
204                                TrackJam::new()
205                                    .with_beam(0)
206                                    .with_emitter(0)
207                                    .with_entity_id(EntityId::new(500, 11111, 71)),
208                            ),
209                    )
210                    .with_beam(
211                        Beam::new()
212                            .with_number(3)
213                            .with_parameter_index(212)
214                            .with_parameter_data(
215                                FundamentalParameterData::new()
216                                    .with_frequency(6_000_000_000f32)
217                                    .with_frequency_range(0f32)
218                                    .with_effective_power(f32::from_be_bytes([
219                                        0x42, 0xf0, 0x00, 0x00,
220                                    ]))
221                                    .with_pulse_repetition_frequency(f32::from_be_bytes([
222                                        0x43, 0xbb, 0x8c, 0x01,
223                                    ]))
224                                    .with_pulse_width(f32::from_be_bytes([0x40, 0xa0, 0x00, 0x00])),
225                            )
226                            .with_beam_data(
227                                BeamData::new()
228                                    .with_azimuth_center(f32::from_be_bytes([
229                                        0x3e, 0x05, 0xd6, 0x14,
230                                    ]))
231                                    .with_azimuth_sweep(f32::from_be_bytes([
232                                        0x3c, 0x0e, 0xfa, 0x35,
233                                    ]))
234                                    .with_elevation_center(f32::from_be_bytes([
235                                        0x3f, 0x30, 0x95, 0x54,
236                                    ]))
237                                    .with_elevation_sweep(f32::from_be_bytes([
238                                        0x3c, 0x0e, 0xfa, 0x35,
239                                    ]))
240                                    .with_sweep_sync(0f32),
241                            )
242                            .with_beam_function(
243                                ElectromagneticEmissionBeamFunction::CommandGuidance,
244                            )
245                            .with_high_density_track_jam(HighDensityTrackJam::NotSelected)
246                            .with_track_jam(
247                                TrackJam::new()
248                                    .with_beam(0)
249                                    .with_emitter(0)
250                                    .with_entity_id(EntityId::new(500, 11111, 71)),
251                            ),
252                    ),
253            )
254            .build()
255            .into_pdu_body();
256
257        let header = PduHeader::new_v6(1, body.body_type());
258        let pdu = Pdu::finalize_from_parts(header, body, 0);
259
260        let mut buf = BytesMut::with_capacity(228);
261
262        let len = pdu.serialize(&mut buf).unwrap();
263        assert_eq!(len, 228);
264
265        let expected: [u8; 228] = [
266            0x06, 0x01, 0x17, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x01, 0xf4,
267            0x2b, 0x67, 0x00, 0x3e, 0x01, 0xf4, 0x2b, 0x67, 0x02, 0x41, 0x00, 0x01, 0x00, 0x00,
268            0x32, 0x03, 0x00, 0x00, 0x7d, 0xaf, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269            0x00, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x7a, 0x4f, 0xb2, 0xd0, 0x5e,
270            0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271            0x00, 0x00, 0x3e, 0x05, 0xd5, 0xff, 0x3c, 0x0e, 0xfa, 0x35, 0x3f, 0x30, 0x95, 0x12,
272            0x3c, 0x0e, 0xfa, 0x35, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
273            0x00, 0x00, 0x01, 0xf4, 0x2b, 0x67, 0x00, 0x47, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x64,
274            0x4f, 0xb2, 0xd0, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0, 0x00, 0x00, 0x45, 0x9c,
275            0x40, 0x00, 0x42, 0x48, 0x00, 0x00, 0x3e, 0x05, 0xd6, 0x14, 0x3c, 0x0e, 0xfa, 0x35,
276            0x3f, 0x30, 0x95, 0x54, 0x3c, 0x0e, 0xfa, 0x35, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01,
277            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x2b, 0x67, 0x00, 0x47, 0x00, 0x00,
278            0x0f, 0x03, 0x00, 0xd4, 0x4f, 0xb2, 0xd0, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf0,
279            0x00, 0x00, 0x43, 0xbb, 0x8c, 0x01, 0x40, 0xa0, 0x00, 0x00, 0x3e, 0x05, 0xd6, 0x14,
280            0x3c, 0x0e, 0xfa, 0x35, 0x3f, 0x30, 0x95, 0x54, 0x3c, 0x0e, 0xfa, 0x35, 0x00, 0x00,
281            0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x2b, 0x67,
282            0x00, 0x47, 0x00, 0x00,
283        ];
284
285        assert_eq!(buf.as_ref(), expected.as_ref());
286    }
287}