dis_rs/common/iff/
model.rs

1use crate::common::iff::builder::{
2    ChangeOptionsRecordBuilder, DapSourceBuilder, EnhancedMode1CodeBuilder,
3    FundamentalOperationalDataBuilder, IffBuilder, IffDataRecordBuilder,
4    IffDataSpecificationBuilder, IffFundamentalParameterDataBuilder, IffLayer2Builder,
5    IffLayer3Builder, IffLayer4Builder, IffLayer5Builder, InformationLayersBuilder,
6    LayerHeaderBuilder, Mode5InterrogatorBasicDataBuilder, Mode5InterrogatorStatusBuilder,
7    Mode5MessageFormatsBuilder, Mode5TransponderBasicDataBuilder, Mode5TransponderStatusBuilder,
8    Mode5TransponderSupplementalDataBuilder, ModeSAltitudeBuilder,
9    ModeSInterrogatorBasicDataBuilder, ModeSInterrogatorStatusBuilder, ModeSLevelsPresentBuilder,
10    ModeSTransponderBasicDataBuilder, ModeSTransponderStatusBuilder, SystemIdBuilder,
11    SystemSpecificDataBuilder, SystemStatusBuilder,
12};
13use crate::common::model::{
14    length_padded_to_num, BeamData, EntityId, EventId, PduBody, SimulationAddress, VectorF32,
15};
16use crate::common::{BodyInfo, Interaction};
17use crate::constants::{
18    BIT_0_IN_BYTE, BIT_1_IN_BYTE, BIT_2_IN_BYTE, BIT_3_IN_BYTE, BIT_4_IN_BYTE, BIT_5_IN_BYTE,
19    BIT_6_IN_BYTE, BIT_7_IN_BYTE, FOUR_OCTETS, SIX_OCTETS,
20};
21use crate::enumerations::{
22    AircraftIdentificationType, AircraftPresentDomain, AntennaSelection, CapabilityReport,
23    DataCategory, IffApplicableModes, IffSystemMode, IffSystemName, IffSystemType,
24    Level2SquitterStatus, Mode5IffMission, Mode5LevelSelection, Mode5LocationErrors,
25    Mode5MessageFormatsStatus, Mode5PlatformType, Mode5Reply, Mode5SAltitudeResolution,
26    ModeSSquitterRecordSource, ModeSSquitterType, ModeSTransmitState, NavigationSource, PduType,
27    VariableRecordType,
28};
29#[cfg(feature = "serde")]
30use serde::{Deserialize, Serialize};
31
32pub const IFF_PDU_LAYER_1_DATA_LENGTH_OCTETS: u16 = 48;
33pub const BASE_IFF_DATA_RECORD_LENGTH_OCTETS: u16 = 6;
34
35/// 7.6.5 Identification Friend or Foe (IFF) PDU
36///
37/// 7.6.5.1 General
38///
39/// 7.6.5.2 Layer 1 basic system data
40#[derive(Clone, Debug, Default, PartialEq)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42pub struct Iff {
43    pub emitting_entity_id: EntityId,
44    pub event_id: EventId,
45    pub relative_antenna_location: VectorF32,
46    pub system_id: SystemId,
47    pub system_designator: u8,    // See item d2) in 5.7.6.1.
48    pub system_specific_data: u8, // 8-bit record defined by system type - See B.5
49    pub fundamental_operational_data: FundamentalOperationalData, // see 6.2.39
50    // Layer 1 up to here
51    pub layer_2: Option<IffLayer2>, // 7.6.5.3 Layer 2 emissions data
52    pub layer_3: Option<IffLayer3>, // Mode 5 Functional Data
53    pub layer_4: Option<IffLayer4>, // Mode S Functional Data
54    pub layer_5: Option<IffLayer5>, // Data Communications
55}
56
57impl Iff {
58    #[must_use]
59    pub fn builder() -> IffBuilder {
60        IffBuilder::new()
61    }
62
63    #[must_use]
64    pub fn into_builder(self) -> IffBuilder {
65        IffBuilder::new_from_body(self)
66    }
67
68    #[must_use]
69    pub fn into_pdu_body(self) -> PduBody {
70        PduBody::IFF(self)
71    }
72}
73
74impl BodyInfo for Iff {
75    fn body_length(&self) -> u16 {
76        IFF_PDU_LAYER_1_DATA_LENGTH_OCTETS
77            + if let Some(layer_2) = &self.layer_2 {
78                layer_2.data_length()
79            } else {
80                0
81            }
82            + if let Some(layer_3) = &self.layer_3 {
83                layer_3.data_length()
84            } else {
85                0
86            }
87            + if let Some(layer_4) = &self.layer_4 {
88                layer_4.data_length()
89            } else {
90                0
91            }
92            + if let Some(layer_5) = &self.layer_5 {
93                layer_5.data_length()
94            } else {
95                0
96            }
97    }
98
99    fn body_type(&self) -> PduType {
100        PduType::IFF
101    }
102}
103
104impl Interaction for Iff {
105    fn originator(&self) -> Option<&EntityId> {
106        Some(&self.emitting_entity_id)
107    }
108
109    fn receiver(&self) -> Option<&EntityId> {
110        None
111    }
112}
113
114/// 7.6.5.3 Layer 2 emissions data
115///
116/// The Secondary Operational Data record (6.2.76) has been flattened in the `IffLayer2` struct, as it only
117/// contains two 8-bit records.
118#[derive(Clone, Debug, PartialEq)]
119#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
120pub struct IffLayer2 {
121    pub layer_header: LayerHeader,
122    pub beam_data: BeamData,
123    pub operational_parameter_1: u8,
124    pub operational_parameter_2: u8,
125    pub iff_fundamental_parameters: Vec<IffFundamentalParameterData>,
126}
127
128impl Default for IffLayer2 {
129    fn default() -> Self {
130        Self {
131            layer_header: LayerHeader {
132                layer_number: 2,
133                ..Default::default()
134            },
135            beam_data: BeamData::default(),
136            operational_parameter_1: 0,
137            operational_parameter_2: 0,
138            iff_fundamental_parameters: vec![IffFundamentalParameterData::default()],
139        }
140    }
141}
142
143impl IffLayer2 {
144    #[must_use]
145    pub fn builder() -> IffLayer2Builder {
146        IffLayer2Builder::new()
147    }
148
149    #[must_use]
150    pub fn data_length(&self) -> u16 {
151        const LAYER_2_BASE_DATA_LENGTH_OCTETS: u16 = 28;
152        const IFF_FUNDAMENTAL_PARAMETER_DATA_LENGTH_OCTETS: u16 = 24;
153        LAYER_2_BASE_DATA_LENGTH_OCTETS
154            + (self.iff_fundamental_parameters.len() as u16
155                * IFF_FUNDAMENTAL_PARAMETER_DATA_LENGTH_OCTETS)
156    }
157
158    #[must_use]
159    pub fn finalize_layer_header_length(mut self) -> Self {
160        self.layer_header.length = self.data_length();
161        self
162    }
163}
164
165/// 7.6.5.4 Layer 3 Mode 5 formats
166/// 7.6.5.4.2 Layer 3 Mode 5 Interrogator Format
167/// 7.6.5.4.3 Layer 3 Mode 5 Transponder Format
168#[derive(Clone, Debug, PartialEq)]
169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
170pub struct IffLayer3 {
171    pub layer_header: LayerHeader,
172    pub reporting_simulation: SimulationAddress,
173    pub mode_5_basic_data: Mode5BasicData,
174    pub data_records: IffDataSpecification, // see 6.2.43 - page 299
175}
176
177impl Default for IffLayer3 {
178    fn default() -> Self {
179        Self {
180            layer_header: LayerHeader {
181                layer_number: 3,
182                ..Default::default()
183            },
184            reporting_simulation: SimulationAddress::default(),
185            mode_5_basic_data: Mode5BasicData::default(),
186            data_records: IffDataSpecification::default(),
187        }
188    }
189}
190
191impl IffLayer3 {
192    #[must_use]
193    pub fn builder() -> IffLayer3Builder {
194        IffLayer3Builder::new()
195    }
196
197    #[must_use]
198    pub fn data_length(&self) -> u16 {
199        const LAYER_3_BASE_DATA_LENGTH_OCTETS: u16 = 26;
200        LAYER_3_BASE_DATA_LENGTH_OCTETS + self.data_records.data_length()
201    }
202
203    #[must_use]
204    pub fn finalize_layer_header_length(mut self) -> Self {
205        self.layer_header.length = self.data_length();
206        self
207    }
208}
209
210/// Custom defined enum to model having either an
211/// Interrogator or a Transponder in an IFF Layer 3 Mode 5 PDU
212#[derive(Clone, Debug, PartialEq)]
213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
214#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
215pub enum Mode5BasicData {
216    Interrogator(Mode5InterrogatorBasicData), // 7.6.5.4.2 Layer 3 Mode 5 Interrogator Format
217    Transponder(Mode5TransponderBasicData),   // 7.6.5.4.3 Layer 3 Mode 5 Transponder Format
218}
219
220impl Default for Mode5BasicData {
221    fn default() -> Self {
222        Self::Interrogator(Mode5InterrogatorBasicData::default())
223    }
224}
225
226impl Mode5BasicData {
227    #[must_use]
228    pub fn new_interrogator(basic_data: Mode5InterrogatorBasicData) -> Self {
229        Self::Interrogator(basic_data)
230    }
231
232    #[must_use]
233    pub fn new_transponder(basic_data: Mode5TransponderBasicData) -> Self {
234        Self::Transponder(basic_data)
235    }
236}
237
238/// 7.6.5.5 Layer 4 Mode S formats
239#[derive(Clone, Debug, PartialEq)]
240#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
241pub struct IffLayer4 {
242    pub layer_header: LayerHeader,
243    pub reporting_simulation: SimulationAddress,
244    pub mode_s_basic_data: ModeSBasicData,
245    pub data_records: IffDataSpecification, // see 6.2.43 - page 299
246}
247
248impl Default for IffLayer4 {
249    fn default() -> Self {
250        Self {
251            layer_header: LayerHeader {
252                layer_number: 4,
253                ..Default::default()
254            },
255            reporting_simulation: SimulationAddress::default(),
256            mode_s_basic_data: ModeSBasicData::default(),
257            data_records: IffDataSpecification::default(),
258        }
259    }
260}
261
262impl IffLayer4 {
263    #[must_use]
264    pub fn builder() -> IffLayer4Builder {
265        IffLayer4Builder::new()
266    }
267
268    #[must_use]
269    pub fn data_length(&self) -> u16 {
270        const LAYER_4_BASE_DATA_LENGTH_OCTETS: u16 = 34;
271        LAYER_4_BASE_DATA_LENGTH_OCTETS + self.data_records.data_length()
272    }
273
274    #[must_use]
275    pub fn finalize_layer_header_length(mut self) -> Self {
276        self.layer_header.length = self.data_length();
277        self
278    }
279}
280
281/// Custom defined enum to model having either an
282/// Interrogator or a Transponder in an IFF Layer 4 Mode S PDU
283#[derive(Clone, Debug, PartialEq)]
284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
285#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
286pub enum ModeSBasicData {
287    Interrogator(ModeSInterrogatorBasicData), // 7.6.5.5.2 Layer 4 Mode S Interrogator Format
288    Transponder(ModeSTransponderBasicData),   // 7.6.5.5.3 Layer 4 Mode S Transponder Format
289}
290
291impl Default for ModeSBasicData {
292    fn default() -> Self {
293        Self::Interrogator(ModeSInterrogatorBasicData::default())
294    }
295}
296
297impl ModeSBasicData {
298    #[must_use]
299    pub fn new_interrogator(basic_data: ModeSInterrogatorBasicData) -> Self {
300        Self::Interrogator(basic_data)
301    }
302
303    #[must_use]
304    pub fn new_transponder(basic_data: ModeSTransponderBasicData) -> Self {
305        Self::Transponder(basic_data)
306    }
307}
308
309/// 7.6.5.6 Layer 5 data communications
310#[derive(Clone, Debug, PartialEq)]
311#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
312pub struct IffLayer5 {
313    pub layer_header: LayerHeader,
314    pub reporting_simulation: SimulationAddress,
315    pub applicable_layers: InformationLayers,
316    pub data_category: DataCategory,
317    pub data_records: IffDataSpecification,
318}
319
320impl Default for IffLayer5 {
321    fn default() -> Self {
322        Self {
323            layer_header: LayerHeader {
324                layer_number: 5,
325                ..Default::default()
326            },
327            reporting_simulation: SimulationAddress::default(),
328            applicable_layers: InformationLayers::default(),
329            data_category: DataCategory::default(),
330            data_records: IffDataSpecification::default(),
331        }
332    }
333}
334
335impl IffLayer5 {
336    #[must_use]
337    pub fn builder() -> IffLayer5Builder {
338        IffLayer5Builder::new()
339    }
340
341    #[must_use]
342    pub fn data_length(&self) -> u16 {
343        const LAYER_5_BASE_DATA_LENGTH_OCTETS: u16 = 14;
344        LAYER_5_BASE_DATA_LENGTH_OCTETS + self.data_records.data_length()
345    }
346
347    #[must_use]
348    pub fn finalize_layer_header_length(mut self) -> Self {
349        self.layer_header.length = self.data_length();
350        self
351    }
352}
353
354/// 6.2.13 Change/Options record
355#[allow(clippy::struct_excessive_bools)]
356#[derive(Copy, Clone, Default, Debug, PartialEq)]
357#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
358pub struct ChangeOptionsRecord {
359    pub change_indicator: bool,
360    pub system_specific_field_1: bool,
361    pub system_specific_field_2: bool,
362    pub heartbeat_indicator: bool,
363    pub transponder_interrogator_indicator: bool,
364    pub simulation_mode: bool,
365    pub interactive_capable: bool,
366    pub test_mode: bool,
367}
368
369impl ChangeOptionsRecord {
370    #[must_use]
371    pub fn builder() -> ChangeOptionsRecordBuilder {
372        ChangeOptionsRecordBuilder::new()
373    }
374}
375
376impl From<u8> for ChangeOptionsRecord {
377    fn from(record: u8) -> Self {
378        let builder = ChangeOptionsRecord::builder();
379        let builder = if ((record & BIT_0_IN_BYTE) >> 7) != 0 {
380            builder.set_change_indicator()
381        } else {
382            builder
383        };
384
385        let builder = if ((record & BIT_1_IN_BYTE) >> 6) != 0 {
386            builder.set_system_specific_field_1()
387        } else {
388            builder
389        };
390
391        let builder = if ((record & BIT_2_IN_BYTE) >> 5) != 0 {
392            builder.set_system_specific_field_2()
393        } else {
394            builder
395        };
396
397        let builder = if ((record & BIT_3_IN_BYTE) >> 4) != 0 {
398            builder.set_heartbeat_indicator()
399        } else {
400            builder
401        };
402
403        let builder = if ((record & BIT_4_IN_BYTE) >> 3) != 0 {
404            builder.set_transponder_interrogator_indicator()
405        } else {
406            builder
407        };
408
409        let builder = if ((record & BIT_5_IN_BYTE) >> 2) != 0 {
410            builder.set_simulation_mode()
411        } else {
412            builder
413        };
414
415        let builder = if ((record & BIT_6_IN_BYTE) >> 1) != 0 {
416            builder.set_interactive_capable()
417        } else {
418            builder
419        };
420
421        let builder = if (record & BIT_7_IN_BYTE) != 0 {
422            builder.set_test_mode()
423        } else {
424            builder
425        };
426
427        builder.build()
428    }
429}
430
431impl From<&ChangeOptionsRecord> for u8 {
432    fn from(value: &ChangeOptionsRecord) -> Self {
433        let mut byte = 0u8;
434        if value.change_indicator {
435            byte += BIT_0_IN_BYTE;
436        }
437        if value.system_specific_field_1 {
438            byte += BIT_1_IN_BYTE;
439        }
440        if value.system_specific_field_2 {
441            byte += BIT_2_IN_BYTE;
442        }
443        if value.heartbeat_indicator {
444            byte += BIT_3_IN_BYTE;
445        }
446        if value.transponder_interrogator_indicator {
447            byte += BIT_4_IN_BYTE;
448        }
449        if value.simulation_mode {
450            byte += BIT_5_IN_BYTE;
451        }
452        if value.interactive_capable {
453            byte += BIT_6_IN_BYTE;
454        }
455        if value.test_mode {
456            byte += BIT_7_IN_BYTE;
457        }
458        byte
459    }
460}
461
462/// 6.2.39 Fundamental Operational Data record
463#[derive(Clone, Default, Debug, PartialEq)]
464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
465pub struct FundamentalOperationalData {
466    pub system_status: SystemStatus,
467    pub data_field_1: u8,
468    pub information_layers: InformationLayers,
469    pub data_field_2: u8,
470    pub parameter_1: u16,
471    pub parameter_2: u16,
472    pub parameter_3: u16,
473    pub parameter_4: u16,
474    pub parameter_5: u16,
475    pub parameter_6: u16,
476}
477
478impl FundamentalOperationalData {
479    #[must_use]
480    pub fn builder() -> FundamentalOperationalDataBuilder {
481        FundamentalOperationalDataBuilder::new()
482    }
483}
484
485/// Custom defined enum to model the capability of a parameter in the
486/// `FundamentalOperationalData` record.
487#[derive(Copy, Clone, Default, Debug, PartialEq)]
488#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
489pub enum ParameterCapable {
490    #[default]
491    Capable,
492    NotCapable,
493}
494
495/// Custom defined enum to model the capability of a parameter in the
496/// `FundamentalOperationalData` record.
497#[derive(Copy, Clone, Default, Debug, PartialEq)]
498#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
499pub enum OperationalStatus {
500    #[default]
501    Operational,
502    SystemFailed,
503}
504
505/// Custom defined enum to model the presence or applicability of an IFF layer
506/// as used in IFF Layer 1.
507#[derive(Copy, Clone, Default, Debug, PartialEq)]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509pub enum LayersPresenceApplicability {
510    #[default]
511    NotPresentApplicable, // 0
512    PresentApplicable, // 1
513}
514
515/// 6.2.43 IFF Data Specification record
516#[derive(Clone, Default, Debug, PartialEq)]
517#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
518pub struct IffDataRecord {
519    pub record_type: VariableRecordType, // UID 66
520    pub record_specific_fields: Vec<u8>,
521}
522
523impl IffDataRecord {
524    #[must_use]
525    pub fn new() -> Self {
526        Self::default()
527    }
528
529    #[must_use]
530    pub fn builder() -> IffDataRecordBuilder {
531        IffDataRecordBuilder::new()
532    }
533
534    #[must_use]
535    pub fn data_length(&self) -> u16 {
536        length_padded_to_num(SIX_OCTETS + self.record_specific_fields.len(), FOUR_OCTETS)
537            .record_length as u16
538    }
539}
540
541/// 6.2.43 IFF Data Specification record
542#[derive(Clone, Default, Debug, PartialEq)]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544pub struct IffDataSpecification {
545    pub iff_data_records: Vec<IffDataRecord>,
546}
547
548impl IffDataSpecification {
549    #[must_use]
550    pub fn new() -> Self {
551        Self {
552            iff_data_records: vec![],
553        }
554    }
555
556    #[must_use]
557    pub fn builder() -> IffDataSpecificationBuilder {
558        IffDataSpecificationBuilder::new()
559    }
560
561    #[must_use]
562    pub fn data_length(&self) -> u16 {
563        const NUMBER_OF_DATA_RECORDS_OCTETS: u16 = 2;
564        let iff_data_records_data_length: u16 = self
565            .iff_data_records
566            .iter()
567            .map(IffDataRecord::data_length)
568            .sum();
569        NUMBER_OF_DATA_RECORDS_OCTETS + iff_data_records_data_length
570    }
571}
572
573/// 6.2.45 Information Layers record
574#[derive(Copy, Clone, Default, Debug, PartialEq)]
575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
576pub struct InformationLayers {
577    pub layer_1: LayersPresenceApplicability,
578    pub layer_2: LayersPresenceApplicability,
579    pub layer_3: LayersPresenceApplicability,
580    pub layer_4: LayersPresenceApplicability,
581    pub layer_5: LayersPresenceApplicability,
582    pub layer_6: LayersPresenceApplicability,
583    pub layer_7: LayersPresenceApplicability,
584}
585
586impl InformationLayers {
587    #[must_use]
588    pub fn builder() -> InformationLayersBuilder {
589        InformationLayersBuilder::new()
590    }
591}
592
593impl From<u8> for InformationLayers {
594    fn from(record: u8) -> Self {
595        let builder = InformationLayers::builder()
596            .with_layer_1(LayersPresenceApplicability::from(
597                (record & BIT_1_IN_BYTE) >> 6,
598            ))
599            .with_layer_2(LayersPresenceApplicability::from(
600                (record & BIT_2_IN_BYTE) >> 5,
601            ))
602            .with_layer_3(LayersPresenceApplicability::from(
603                (record & BIT_3_IN_BYTE) >> 4,
604            ))
605            .with_layer_4(LayersPresenceApplicability::from(
606                (record & BIT_4_IN_BYTE) >> 3,
607            ))
608            .with_layer_5(LayersPresenceApplicability::from(
609                (record & BIT_5_IN_BYTE) >> 2,
610            ))
611            .with_layer_6(LayersPresenceApplicability::from(
612                (record & BIT_6_IN_BYTE) >> 1,
613            ))
614            .with_layer_7(LayersPresenceApplicability::from(record & BIT_7_IN_BYTE));
615
616        builder.build()
617    }
618}
619
620impl From<&InformationLayers> for u8 {
621    fn from(value: &InformationLayers) -> Self {
622        let layer_1 = u8::from(&value.layer_1) << 6;
623        let layer_2 = u8::from(&value.layer_2) << 5;
624        let layer_3 = u8::from(&value.layer_3) << 4;
625        let layer_4 = u8::from(&value.layer_4) << 3;
626        let layer_5 = u8::from(&value.layer_5) << 2;
627        let layer_6 = u8::from(&value.layer_6) << 1;
628        let layer_7 = u8::from(&value.layer_7);
629
630        layer_1 | layer_2 | layer_3 | layer_4 | layer_5 | layer_6 | layer_7
631    }
632}
633
634/// 6.2.44 IFF Fundamental Parameter Data Record
635#[derive(Clone, Default, Debug, PartialEq)]
636#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
637pub struct IffFundamentalParameterData {
638    pub erp: f32,
639    pub frequency: f32,
640    pub pgrf: f32,
641    pub pulse_width: f32,
642    pub burst_length: f32,
643    pub applicable_modes: IffApplicableModes,
644    pub system_specific_data: SystemSpecificData,
645}
646
647impl IffFundamentalParameterData {
648    #[must_use]
649    pub fn builder() -> IffFundamentalParameterDataBuilder {
650        IffFundamentalParameterDataBuilder::new()
651    }
652}
653
654/// 6.2.51 Layer Header
655#[derive(Clone, Default, Debug, PartialEq)]
656#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
657pub struct LayerHeader {
658    pub layer_number: u8,
659    pub layer_specific_information: u8,
660    pub length: u16,
661}
662
663impl LayerHeader {
664    #[must_use]
665    pub fn new() -> Self {
666        LayerHeader::default()
667    }
668
669    #[must_use]
670    pub fn builder() -> LayerHeaderBuilder {
671        LayerHeaderBuilder::new()
672    }
673}
674
675// TODO placeholder for 24-bits - See Annex B.
676#[derive(Copy, Clone, Default, Debug, PartialEq)]
677#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
678pub struct SystemSpecificData {
679    pub part_1: u8,
680    pub part_2: u8,
681    pub part_3: u8,
682}
683
684impl SystemSpecificData {
685    #[must_use]
686    pub fn new() -> Self {
687        SystemSpecificData::default()
688    }
689
690    #[must_use]
691    pub fn builder() -> SystemSpecificDataBuilder {
692        SystemSpecificDataBuilder::new()
693    }
694}
695
696/// 6.2.87 System Identifier record
697#[derive(Copy, Clone, Default, Debug, PartialEq)]
698#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
699pub struct SystemId {
700    pub system_type: IffSystemType,
701    pub system_name: IffSystemName,
702    pub system_mode: IffSystemMode,
703    pub change_options: ChangeOptionsRecord,
704}
705
706impl SystemId {
707    #[must_use]
708    pub fn new() -> Self {
709        SystemId::default()
710    }
711
712    #[must_use]
713    pub fn builder() -> SystemIdBuilder {
714        SystemIdBuilder::new()
715    }
716}
717
718/// B.2.6 DAP Source record
719/// Downlink of Aircraft Parameters
720#[derive(Clone, Default, Debug, PartialEq)]
721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
722pub struct DapSource {
723    pub indicated_air_speed: DapValue,
724    pub mach_number: DapValue,
725    pub ground_speed: DapValue,
726    pub magnetic_heading: DapValue,
727    pub track_angle_rate: DapValue,
728    pub true_track_angle: DapValue,
729    pub true_airspeed: DapValue,
730    pub vertical_rate: DapValue,
731}
732
733impl DapSource {
734    #[must_use]
735    pub fn new() -> Self {
736        DapSource::default()
737    }
738
739    #[must_use]
740    pub fn builder() -> DapSourceBuilder {
741        DapSourceBuilder::new()
742    }
743}
744
745impl From<u8> for DapSource {
746    fn from(record: u8) -> Self {
747        let indicated_air_speed = DapValue::from((record & BIT_0_IN_BYTE) >> 7);
748        let mach_number = DapValue::from((record & BIT_1_IN_BYTE) >> 6);
749        let ground_speed = DapValue::from((record & BIT_2_IN_BYTE) >> 5);
750        let magnetic_heading = DapValue::from((record & BIT_3_IN_BYTE) >> 4);
751        let track_angle_rate = DapValue::from((record & BIT_4_IN_BYTE) >> 3);
752        let true_track_angle = DapValue::from((record & BIT_5_IN_BYTE) >> 2);
753        let true_airspeed = DapValue::from((record & BIT_6_IN_BYTE) >> 1);
754        let vertical_rate = DapValue::from(record & BIT_7_IN_BYTE);
755
756        DapSource::builder()
757            .with_indicated_air_speed(indicated_air_speed)
758            .with_mach_number(mach_number)
759            .with_ground_speed(ground_speed)
760            .with_magnetic_heading(magnetic_heading)
761            .with_track_angle_rate(track_angle_rate)
762            .with_true_track_angle(true_track_angle)
763            .with_true_airspeed(true_airspeed)
764            .with_vertical_rate(vertical_rate)
765            .build()
766    }
767}
768
769impl From<&DapSource> for u8 {
770    fn from(value: &DapSource) -> Self {
771        let indicated_air_speed = u8::from(&value.indicated_air_speed) << 7;
772        let mach_number = u8::from(&value.mach_number) << 6;
773        let ground_speed = u8::from(&value.ground_speed) << 5;
774        let magnetic_heading = u8::from(&value.magnetic_heading) << 4;
775        let track_angle_rate = u8::from(&value.track_angle_rate) << 3;
776        let true_track_angle = u8::from(&value.true_track_angle) << 2;
777        let true_airspeed = u8::from(&value.true_airspeed) << 1;
778        let vertical_rate = u8::from(&value.vertical_rate);
779
780        indicated_air_speed
781            | mach_number
782            | ground_speed
783            | magnetic_heading
784            | track_angle_rate
785            | true_track_angle
786            | true_airspeed
787            | vertical_rate
788    }
789}
790
791/// Custom defined enum to model values in the DAP Source record
792#[derive(Clone, Default, Debug, PartialEq)]
793#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
794pub enum DapValue {
795    #[default]
796    ComputeLocally, // 0
797    DataRecordAvailable, // 1
798}
799
800/// B.2.9 Enhanced Mode 1 Code record
801#[derive(Clone, Default, Debug, PartialEq)]
802#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
803pub struct EnhancedMode1Code {
804    pub code_element_1_d: u16,
805    pub code_element_2_c: u16,
806    pub code_element_3_b: u16,
807    pub code_element_4_a: u16,
808    pub on_off_status: OnOffStatus,
809    pub damage_status: DamageStatus,
810    pub malfunction_status: MalfunctionStatus,
811}
812
813impl EnhancedMode1Code {
814    #[must_use]
815    pub fn new() -> Self {
816        EnhancedMode1Code::default()
817    }
818
819    #[must_use]
820    pub fn builder() -> EnhancedMode1CodeBuilder {
821        EnhancedMode1CodeBuilder::new()
822    }
823}
824
825impl From<u16> for EnhancedMode1Code {
826    fn from(record: u16) -> Self {
827        const BITS_0_2: u16 = 0xE000;
828        const BITS_3_5: u16 = 0x1C00;
829        const BITS_6_8: u16 = 0x0380;
830        const BITS_9_11: u16 = 0x0070;
831        const BITS_13: u16 = 0x0004;
832        const BITS_14: u16 = 0x0002;
833        const BITS_15: u16 = 0x0001;
834
835        let code_element_1_d = (record & BITS_0_2) >> 13;
836        let code_element_2_c = (record & BITS_3_5) >> 10;
837        let code_element_3_b = (record & BITS_6_8) >> 7;
838        let code_element_4_a = (record & BITS_9_11) >> 4;
839        let on_off_status = OnOffStatus::from(((record & BITS_13) >> 2) as u8);
840        let damage_status = DamageStatus::from(((record & BITS_14) >> 1) as u8);
841        let malfunction_status = MalfunctionStatus::from((record & BITS_15) as u8);
842
843        EnhancedMode1Code::builder()
844            .with_code_element_1_d(code_element_1_d)
845            .with_code_element_2_c(code_element_2_c)
846            .with_code_element_3_b(code_element_3_b)
847            .with_code_element_4_a(code_element_4_a)
848            .with_on_off_status(on_off_status)
849            .with_damage_status(damage_status)
850            .with_malfunction_status(malfunction_status)
851            .build()
852    }
853}
854
855impl From<&EnhancedMode1Code> for u16 {
856    fn from(value: &EnhancedMode1Code) -> Self {
857        let code_element_1: u16 = value.code_element_1_d << 13;
858        let code_element_2: u16 = value.code_element_2_c << 10;
859        let code_element_3: u16 = value.code_element_3_b << 7;
860        let code_element_4: u16 = value.code_element_4_a << 4;
861        let on_off_status: u16 = u16::from(u8::from(&value.on_off_status)) << 2;
862        let damage_status: u16 = u16::from(u8::from(&value.damage_status)) << 1;
863        let malfunction_status: u16 = u16::from(u8::from(&value.malfunction_status));
864
865        code_element_1
866            | code_element_2
867            | code_element_3
868            | code_element_4
869            | on_off_status
870            | damage_status
871            | malfunction_status
872    }
873}
874
875/// B.2.26 Mode 5 Interrogator Basic Data record
876#[derive(Clone, Default, Debug, PartialEq)]
877#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
878pub struct Mode5InterrogatorBasicData {
879    pub status: Mode5InterrogatorStatus, // B.2.27 Mode 5 Interrogator Status record - page 592
880    pub mode_5_message_formats_present: Mode5MessageFormats, // B.2.28 Mode 5 Message Formats record - page 592
881    pub interrogated_entity_id: EntityId,
882}
883
884impl Mode5InterrogatorBasicData {
885    #[must_use]
886    pub fn new() -> Self {
887        Mode5InterrogatorBasicData::default()
888    }
889
890    #[must_use]
891    pub fn builder() -> Mode5InterrogatorBasicDataBuilder {
892        Mode5InterrogatorBasicDataBuilder::new()
893    }
894}
895
896/// B.2.27 Mode 5 Interrogator Status record
897#[derive(Clone, Default, Debug, PartialEq)]
898#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
899pub struct Mode5InterrogatorStatus {
900    pub iff_mission: Mode5IffMission,
901    pub mode_5_message_formats_status: Mode5MessageFormatsStatus,
902    pub on_off_status: OnOffStatus,
903    pub damage_status: DamageStatus,
904    pub malfunction_status: MalfunctionStatus,
905}
906
907impl Mode5InterrogatorStatus {
908    #[must_use]
909    pub fn new() -> Self {
910        Mode5InterrogatorStatus::default()
911    }
912
913    #[must_use]
914    pub fn builder() -> Mode5InterrogatorStatusBuilder {
915        Mode5InterrogatorStatusBuilder::new()
916    }
917}
918
919impl From<u8> for Mode5InterrogatorStatus {
920    fn from(record: u8) -> Self {
921        const BITS_0_2: u8 = 0xE0;
922        let iff_mission = Mode5IffMission::from((record & BITS_0_2) >> 5);
923        let mode_5_message_formats_status =
924            Mode5MessageFormatsStatus::from((record & BIT_3_IN_BYTE) >> 4);
925        let on_off_status = OnOffStatus::from((record & BIT_5_IN_BYTE) >> 2);
926        let damage_status = DamageStatus::from((record & BIT_6_IN_BYTE) >> 1);
927        let malfunction_status = MalfunctionStatus::from(record & BIT_7_IN_BYTE);
928
929        Mode5InterrogatorStatus::builder()
930            .with_iff_mission(iff_mission)
931            .with_mode_5_message_formats_status(mode_5_message_formats_status)
932            .with_on_off_status(on_off_status)
933            .with_damage_status(damage_status)
934            .with_malfunction_status(malfunction_status)
935            .build()
936    }
937}
938
939impl From<&Mode5InterrogatorStatus> for u8 {
940    fn from(value: &Mode5InterrogatorStatus) -> Self {
941        let iff_mission: u8 = u8::from(value.iff_mission) << 5;
942        let message_formats_status: u8 = u8::from(value.mode_5_message_formats_status) << 4;
943        let on_off_status: u8 = u8::from(&value.on_off_status) << 2;
944        let damage_status: u8 = u8::from(&value.damage_status) << 1;
945        let malfunction_status: u8 = u8::from(&value.malfunction_status);
946
947        iff_mission | message_formats_status | on_off_status | damage_status | malfunction_status
948    }
949}
950
951/// B.2.28 Mode 5 Message Formats record
952#[derive(Clone, Default, Debug, PartialEq)]
953#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
954pub struct Mode5MessageFormats {
955    pub message_format_0: IffPresence, // 0 - Not Present, 1 - Present
956    pub message_format_1: IffPresence,
957    pub message_format_2: IffPresence,
958    pub message_format_3: IffPresence,
959    pub message_format_4: IffPresence,
960    pub message_format_5: IffPresence,
961    pub message_format_6: IffPresence,
962    pub message_format_7: IffPresence,
963    pub message_format_8: IffPresence,
964    pub message_format_9: IffPresence,
965    pub message_format_10: IffPresence,
966    pub message_format_11: IffPresence,
967    pub message_format_12: IffPresence,
968    pub message_format_13: IffPresence,
969    pub message_format_14: IffPresence,
970    pub message_format_15: IffPresence,
971    pub message_format_16: IffPresence,
972    pub message_format_17: IffPresence,
973    pub message_format_18: IffPresence,
974    pub message_format_19: IffPresence,
975    pub message_format_20: IffPresence,
976    pub message_format_21: IffPresence,
977    pub message_format_22: IffPresence,
978    pub message_format_23: IffPresence,
979    pub message_format_24: IffPresence,
980    pub message_format_25: IffPresence,
981    pub message_format_26: IffPresence,
982    pub message_format_27: IffPresence,
983    pub message_format_28: IffPresence,
984    pub message_format_29: IffPresence,
985    pub message_format_30: IffPresence,
986    pub message_format_31: IffPresence,
987}
988
989impl Mode5MessageFormats {
990    #[must_use]
991    pub fn new() -> Self {
992        Mode5MessageFormats::default()
993    }
994
995    #[must_use]
996    pub fn builder() -> Mode5MessageFormatsBuilder {
997        Mode5MessageFormatsBuilder::new()
998    }
999}
1000
1001impl From<u32> for Mode5MessageFormats {
1002    #[allow(clippy::cast_possible_truncation)]
1003    #[allow(clippy::similar_names)]
1004    fn from(record: u32) -> Self {
1005        let format_0 = IffPresence::from(((record >> 31) as u8) & BIT_7_IN_BYTE);
1006        let format_1 = IffPresence::from(((record >> 30) as u8) & BIT_7_IN_BYTE);
1007        let format_2 = IffPresence::from(((record >> 29) as u8) & BIT_7_IN_BYTE);
1008        let format_3 = IffPresence::from(((record >> 28) as u8) & BIT_7_IN_BYTE);
1009        let format_4 = IffPresence::from(((record >> 27) as u8) & BIT_7_IN_BYTE);
1010        let format_5 = IffPresence::from(((record >> 26) as u8) & BIT_7_IN_BYTE);
1011        let format_6 = IffPresence::from(((record >> 25) as u8) & BIT_7_IN_BYTE);
1012        let format_7 = IffPresence::from(((record >> 24) as u8) & BIT_7_IN_BYTE);
1013        let format_8 = IffPresence::from(((record >> 23) as u8) & BIT_7_IN_BYTE);
1014        let format_9 = IffPresence::from(((record >> 22) as u8) & BIT_7_IN_BYTE);
1015        let format_10 = IffPresence::from(((record >> 21) as u8) & BIT_7_IN_BYTE);
1016        let format_11 = IffPresence::from(((record >> 20) as u8) & BIT_7_IN_BYTE);
1017        let format_12 = IffPresence::from(((record >> 19) as u8) & BIT_7_IN_BYTE);
1018        let format_13 = IffPresence::from(((record >> 18) as u8) & BIT_7_IN_BYTE);
1019        let format_14 = IffPresence::from(((record >> 17) as u8) & BIT_7_IN_BYTE);
1020        let format_15 = IffPresence::from(((record >> 16) as u8) & BIT_7_IN_BYTE);
1021        let format_16 = IffPresence::from(((record >> 15) as u8) & BIT_7_IN_BYTE);
1022        let format_17 = IffPresence::from(((record >> 14) as u8) & BIT_7_IN_BYTE);
1023        let format_18 = IffPresence::from(((record >> 13) as u8) & BIT_7_IN_BYTE);
1024        let format_19 = IffPresence::from(((record >> 12) as u8) & BIT_7_IN_BYTE);
1025        let format_20 = IffPresence::from(((record >> 11) as u8) & BIT_7_IN_BYTE);
1026        let format_21 = IffPresence::from(((record >> 10) as u8) & BIT_7_IN_BYTE);
1027        let format_22 = IffPresence::from(((record >> 9) as u8) & BIT_7_IN_BYTE);
1028        let format_23 = IffPresence::from(((record >> 8) as u8) & BIT_7_IN_BYTE);
1029        let format_24 = IffPresence::from(((record >> 7) as u8) & BIT_7_IN_BYTE);
1030        let format_25 = IffPresence::from(((record >> 6) as u8) & BIT_7_IN_BYTE);
1031        let format_26 = IffPresence::from(((record >> 5) as u8) & BIT_7_IN_BYTE);
1032        let format_27 = IffPresence::from(((record >> 4) as u8) & BIT_7_IN_BYTE);
1033        let format_28 = IffPresence::from(((record >> 3) as u8) & BIT_7_IN_BYTE);
1034        let format_29 = IffPresence::from(((record >> 2) as u8) & BIT_7_IN_BYTE);
1035        let format_30 = IffPresence::from(((record >> 1) as u8) & BIT_7_IN_BYTE);
1036        let format_31 = IffPresence::from((record as u8) & BIT_7_IN_BYTE);
1037
1038        Mode5MessageFormats::builder()
1039            .with_message_format_0(format_0)
1040            .with_message_format_1(format_1)
1041            .with_message_format_2(format_2)
1042            .with_message_format_3(format_3)
1043            .with_message_format_4(format_4)
1044            .with_message_format_5(format_5)
1045            .with_message_format_6(format_6)
1046            .with_message_format_7(format_7)
1047            .with_message_format_8(format_8)
1048            .with_message_format_9(format_9)
1049            .with_message_format_10(format_10)
1050            .with_message_format_11(format_11)
1051            .with_message_format_12(format_12)
1052            .with_message_format_13(format_13)
1053            .with_message_format_14(format_14)
1054            .with_message_format_15(format_15)
1055            .with_message_format_16(format_16)
1056            .with_message_format_17(format_17)
1057            .with_message_format_18(format_18)
1058            .with_message_format_19(format_19)
1059            .with_message_format_20(format_20)
1060            .with_message_format_21(format_21)
1061            .with_message_format_22(format_22)
1062            .with_message_format_23(format_23)
1063            .with_message_format_24(format_24)
1064            .with_message_format_25(format_25)
1065            .with_message_format_26(format_26)
1066            .with_message_format_27(format_27)
1067            .with_message_format_28(format_28)
1068            .with_message_format_29(format_29)
1069            .with_message_format_30(format_30)
1070            .with_message_format_31(format_31)
1071            .build()
1072    }
1073}
1074
1075impl From<&Mode5MessageFormats> for u32 {
1076    #[allow(clippy::similar_names)]
1077    fn from(value: &Mode5MessageFormats) -> Self {
1078        let mf_0 = u32::from(&value.message_format_0) << 31;
1079        let mf_1 = u32::from(&value.message_format_1) << 30;
1080        let mf_2 = u32::from(&value.message_format_2) << 29;
1081        let mf_3 = u32::from(&value.message_format_3) << 28;
1082        let mf_4 = u32::from(&value.message_format_4) << 27;
1083        let mf_5 = u32::from(&value.message_format_5) << 26;
1084        let mf_6 = u32::from(&value.message_format_6) << 25;
1085        let mf_7 = u32::from(&value.message_format_7) << 24;
1086        let mf_8 = u32::from(&value.message_format_8) << 23;
1087        let mf_9 = u32::from(&value.message_format_9) << 22;
1088        let mf_10 = u32::from(&value.message_format_10) << 21;
1089        let mf_11 = u32::from(&value.message_format_11) << 20;
1090        let mf_12 = u32::from(&value.message_format_12) << 19;
1091        let mf_13 = u32::from(&value.message_format_13) << 18;
1092        let mf_14 = u32::from(&value.message_format_14) << 17;
1093        let mf_15 = u32::from(&value.message_format_15) << 16;
1094        let mf_16 = u32::from(&value.message_format_16) << 15;
1095        let mf_17 = u32::from(&value.message_format_17) << 14;
1096        let mf_18 = u32::from(&value.message_format_18) << 13;
1097        let mf_19 = u32::from(&value.message_format_19) << 12;
1098        let mf_20 = u32::from(&value.message_format_20) << 11;
1099        let mf_21 = u32::from(&value.message_format_21) << 10;
1100        let mf_22 = u32::from(&value.message_format_22) << 9;
1101        let mf_23 = u32::from(&value.message_format_23) << 8;
1102        let mf_24 = u32::from(&value.message_format_24) << 7;
1103        let mf_25 = u32::from(&value.message_format_25) << 6;
1104        let mf_26 = u32::from(&value.message_format_26) << 5;
1105        let mf_27 = u32::from(&value.message_format_27) << 4;
1106        let mf_28 = u32::from(&value.message_format_28) << 3;
1107        let mf_29 = u32::from(&value.message_format_29) << 2;
1108        let mf_30 = u32::from(&value.message_format_30) << 1;
1109        let mf_31 = u32::from(&value.message_format_31);
1110
1111        mf_0 | mf_1
1112            | mf_2
1113            | mf_3
1114            | mf_4
1115            | mf_5
1116            | mf_6
1117            | mf_7
1118            | mf_8
1119            | mf_9
1120            | mf_10
1121            | mf_11
1122            | mf_12
1123            | mf_13
1124            | mf_14
1125            | mf_15
1126            | mf_16
1127            | mf_17
1128            | mf_18
1129            | mf_19
1130            | mf_20
1131            | mf_21
1132            | mf_22
1133            | mf_23
1134            | mf_24
1135            | mf_25
1136            | mf_26
1137            | mf_27
1138            | mf_28
1139            | mf_29
1140            | mf_30
1141            | mf_31
1142    }
1143}
1144
1145/// B.2.29 Mode 5 Transponder Basic Data record
1146#[derive(Clone, Default, Debug, PartialEq)]
1147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1148pub struct Mode5TransponderBasicData {
1149    pub status: Mode5TransponderStatus,
1150    pub pin: u16,
1151    pub mode_5_message_formats_present: Mode5MessageFormats, // B.2.28 Mode 5 Message Formats record
1152    pub enhanced_mode_1: EnhancedMode1Code,                  // B.2.9 Enhanced Mode 1 Code record
1153    pub national_origin: u16,                                // 16-bit undefined enumeration
1154    pub supplemental_data: Mode5TransponderSupplementalData, // B.2.31 Mode 5 Transponder SD record
1155    pub navigation_source: NavigationSource,                 // UID 359
1156    pub figure_of_merit: u8,                                 // 8-bit uint between 0 and 31 decimal
1157}
1158
1159impl Mode5TransponderBasicData {
1160    #[must_use]
1161    pub fn new() -> Self {
1162        Mode5TransponderBasicData::default()
1163    }
1164
1165    #[must_use]
1166    pub fn builder() -> Mode5TransponderBasicDataBuilder {
1167        Mode5TransponderBasicDataBuilder::new()
1168    }
1169}
1170
1171/// Custom defined enum to model a system being On or Off.
1172#[derive(Copy, Clone, Default, Debug, PartialEq)]
1173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1174pub enum OnOffStatus {
1175    #[default]
1176    Off, // 0
1177    On, // 1
1178}
1179
1180/// Custom defined enum to model a system being Not Damaged or Damaged.
1181#[derive(Clone, Default, Debug, PartialEq)]
1182#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1183pub enum DamageStatus {
1184    #[default]
1185    NoDamage, // 0
1186    Damaged, // 1
1187}
1188
1189/// Custom defined enum to model a system being Not Malfunctioning or Malfunctioning.
1190#[derive(Clone, Default, Debug, PartialEq)]
1191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1192pub enum MalfunctionStatus {
1193    #[default]
1194    NoMalfunction, // 0
1195    Malfunction, // 1
1196}
1197
1198/// Custom defined enum to model a system being Not Enabled or Enabled.
1199#[derive(Clone, Default, Debug, PartialEq)]
1200#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1201pub enum EnabledStatus {
1202    #[default]
1203    NotEnabled, // 0
1204    Enabled, // 1
1205}
1206
1207/// Custom defined enum to model the source of
1208/// Mode 5 latitude, longitude, and altitude information.
1209#[derive(Clone, Default, Debug, PartialEq)]
1210#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1211pub enum LatLonAltSource {
1212    #[default]
1213    ComputeLocally, // 0
1214    TransponderLocationDataRecordPresent, // 1
1215}
1216
1217/// B.2.31 Mode 5 Transponder Supplemental Data (SD) record
1218#[derive(Clone, Default, Debug, PartialEq)]
1219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1220pub struct Mode5TransponderSupplementalData {
1221    pub squitter_on_off_status: SquitterStatus,
1222    pub level_2_squitter_status: Level2SquitterStatus,
1223    pub iff_mission: Mode5IffMission,
1224}
1225
1226impl Mode5TransponderSupplementalData {
1227    #[must_use]
1228    pub fn new() -> Self {
1229        Mode5TransponderSupplementalData::default()
1230    }
1231
1232    #[must_use]
1233    pub fn builder() -> Mode5TransponderSupplementalDataBuilder {
1234        Mode5TransponderSupplementalDataBuilder::new()
1235    }
1236}
1237
1238impl From<u8> for Mode5TransponderSupplementalData {
1239    fn from(record: u8) -> Self {
1240        const BITS_2_4: u8 = 0x38;
1241        let squitter_status = SquitterStatus::from((record & BIT_0_IN_BYTE) >> 7);
1242        let level_2_squitter_status = Level2SquitterStatus::from((record & BIT_1_IN_BYTE) >> 6);
1243        let iff_mission = Mode5IffMission::from((record & BITS_2_4) >> 3);
1244
1245        Mode5TransponderSupplementalData::builder()
1246            .with_squitter_on_off_status(squitter_status)
1247            .with_level_2_squitter_status(level_2_squitter_status)
1248            .with_iff_mission(iff_mission)
1249            .build()
1250    }
1251}
1252
1253impl From<&Mode5TransponderSupplementalData> for u8 {
1254    fn from(value: &Mode5TransponderSupplementalData) -> Self {
1255        let squitter_status: u8 = u8::from(&value.squitter_on_off_status) << 7;
1256        let level_2_squitter_status: u8 = u8::from(value.level_2_squitter_status) << 6;
1257        let iff_mission: u8 = u8::from(value.iff_mission) << 3;
1258
1259        squitter_status | level_2_squitter_status | iff_mission
1260    }
1261}
1262
1263/// B.2.32 Mode 5 Transponder Status record
1264#[derive(Clone, Default, Debug, PartialEq)]
1265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1266pub struct Mode5TransponderStatus {
1267    pub mode_5_reply: Mode5Reply,
1268    pub line_test: EnabledStatus,
1269    pub antenna_selection: AntennaSelection,
1270    pub crypto_control: IffPresence,
1271    pub lat_lon_alt_source: LatLonAltSource,
1272    pub location_errors: Mode5LocationErrors,
1273    pub platform_type: Mode5PlatformType,
1274    pub mode_5_level_selection: Mode5LevelSelection,
1275    pub on_off_status: OnOffStatus,
1276    pub damage_status: DamageStatus,
1277    pub malfunction_status: MalfunctionStatus,
1278}
1279
1280impl Mode5TransponderStatus {
1281    #[must_use]
1282    pub fn new() -> Self {
1283        Mode5TransponderStatus::default()
1284    }
1285
1286    #[must_use]
1287    pub fn builder() -> Mode5TransponderStatusBuilder {
1288        Mode5TransponderStatusBuilder::new()
1289    }
1290}
1291
1292impl From<u16> for Mode5TransponderStatus {
1293    fn from(record: u16) -> Self {
1294        const BITS_0_3: u16 = 0xF000;
1295        const BIT_4: u16 = 0x0800;
1296        const BITS_5_6: u16 = 0x0600;
1297        const BIT_7: u16 = 0x0100;
1298        const BIT_8: u16 = 0x0080;
1299        const BIT_9: u16 = 0x0040;
1300        const BIT_10: u16 = 0x0020;
1301        const BIT_11: u16 = 0x0010;
1302        const BIT_13: u16 = 0x0004;
1303        const BIT_14: u16 = 0x0002;
1304        const BIT_15: u16 = 0x0001;
1305        let mode_5_reply = Mode5Reply::from(((record & BITS_0_3) >> 12) as u8);
1306        let line_test = EnabledStatus::from(((record & BIT_4) >> 11) as u8);
1307        let antenna_selection = AntennaSelection::from(((record & BITS_5_6) >> 9) as u8);
1308        let crypto_control = IffPresence::from(((record & BIT_7) >> 8) as u8);
1309        let lat_lon_alt_source = LatLonAltSource::from(((record & BIT_8) >> 7) as u8);
1310        let location_errors = Mode5LocationErrors::from(((record & BIT_9) >> 6) as u8);
1311        let platform_type = Mode5PlatformType::from(((record & BIT_10) >> 5) as u8);
1312        let mode_5_level_selection = Mode5LevelSelection::from(((record & BIT_11) >> 4) as u8);
1313        let on_off_status = OnOffStatus::from(((record & BIT_13) >> 2) as u8);
1314        let damage_status = DamageStatus::from(((record & BIT_14) >> 1) as u8);
1315        let malfunction_status = MalfunctionStatus::from((record & BIT_15) as u8);
1316
1317        Mode5TransponderStatus::builder()
1318            .with_mode_5_reply(mode_5_reply)
1319            .with_line_test(line_test)
1320            .with_antenna_selection(antenna_selection)
1321            .with_crypto_control(crypto_control)
1322            .with_lat_lon_alt_source(lat_lon_alt_source)
1323            .with_location_errors(location_errors)
1324            .with_platform_type(platform_type)
1325            .with_mode_5_level_selection(mode_5_level_selection)
1326            .with_on_off_status(on_off_status)
1327            .with_damage_status(damage_status)
1328            .with_malfunction_status(malfunction_status)
1329            .build()
1330    }
1331}
1332
1333impl From<&Mode5TransponderStatus> for u16 {
1334    fn from(value: &Mode5TransponderStatus) -> Self {
1335        let mode_5_reply: u8 = u8::from(value.mode_5_reply) << 4;
1336        let line_test: u8 = u8::from(&value.line_test) << 3;
1337        let antenna_selection: u8 = u8::from(value.antenna_selection) << 1;
1338        let crypto_control: u8 = u32::from(&value.crypto_control) as u8;
1339
1340        let byte_1 = mode_5_reply | line_test | antenna_selection | crypto_control;
1341
1342        let lat_lon_alt_source: u8 = u8::from(&value.lat_lon_alt_source) << 7;
1343        let location_errors: u8 = u8::from(value.location_errors) << 6;
1344        let platform_type: u8 = u8::from(value.platform_type) << 5;
1345        let mode_5_level_selection: u8 = u8::from(value.mode_5_level_selection) << 4;
1346        let on_off_status: u8 = u8::from(&value.on_off_status) << 2;
1347        let damage_status: u8 = u8::from(&value.damage_status) << 1;
1348        let malfunction_status: u8 = (&value.malfunction_status).into();
1349
1350        let byte_2 = lat_lon_alt_source
1351            | location_errors
1352            | platform_type
1353            | mode_5_level_selection
1354            | on_off_status
1355            | damage_status
1356            | malfunction_status;
1357
1358        (u16::from(byte_1) << 8) | u16::from(byte_2)
1359    }
1360}
1361
1362/// B.2.36 Mode S Altitude record
1363#[derive(Clone, Default, Debug, PartialEq)]
1364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1365pub struct ModeSAltitude {
1366    pub altitude: u16,
1367    pub resolution: Mode5SAltitudeResolution,
1368}
1369
1370impl ModeSAltitude {
1371    #[must_use]
1372    pub fn new() -> Self {
1373        ModeSAltitude::default()
1374    }
1375
1376    #[must_use]
1377    pub fn builder() -> ModeSAltitudeBuilder {
1378        ModeSAltitudeBuilder::new()
1379    }
1380}
1381
1382impl From<u16> for ModeSAltitude {
1383    fn from(record: u16) -> Self {
1384        const BITS_0_10: u16 = 0xFFE0;
1385        const BIT_11: u16 = 0x0010;
1386        let altitude = (record & BITS_0_10) >> 5;
1387        let resolution = Mode5SAltitudeResolution::from(((record & BIT_11) as u8) >> 4);
1388
1389        ModeSAltitude::builder()
1390            .with_altitude(altitude)
1391            .with_resolution(resolution)
1392            .build()
1393    }
1394}
1395
1396impl From<&ModeSAltitude> for u16 {
1397    fn from(value: &ModeSAltitude) -> Self {
1398        let resolution: u8 = value.resolution.into();
1399        let resolution: u16 = u16::from(resolution);
1400
1401        (value.altitude << 5) | (resolution << 4)
1402    }
1403}
1404
1405/// B.2.37 Mode S Interrogator Basic Data record
1406#[derive(Clone, Default, Debug, PartialEq)]
1407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1408pub struct ModeSInterrogatorBasicData {
1409    pub mode_s_interrogator_status: ModeSInterrogatorStatus,
1410    pub mode_s_levels_present: ModeSLevelsPresent,
1411}
1412
1413impl ModeSInterrogatorBasicData {
1414    #[must_use]
1415    pub fn new() -> Self {
1416        ModeSInterrogatorBasicData::default()
1417    }
1418
1419    #[must_use]
1420    pub fn builder() -> ModeSInterrogatorBasicDataBuilder {
1421        ModeSInterrogatorBasicDataBuilder::new()
1422    }
1423}
1424
1425/// B.2.39 Mode S Interrogator Status record
1426#[derive(Clone, Default, Debug, PartialEq)]
1427#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1428pub struct ModeSInterrogatorStatus {
1429    pub on_off_status: OnOffStatus,
1430    pub transmit_state: ModeSTransmitState,
1431    pub damage_status: DamageStatus,
1432    pub malfunction_status: MalfunctionStatus,
1433}
1434
1435impl ModeSInterrogatorStatus {
1436    #[must_use]
1437    pub fn new() -> Self {
1438        ModeSInterrogatorStatus::default()
1439    }
1440
1441    #[must_use]
1442    pub fn builder() -> ModeSInterrogatorStatusBuilder {
1443        ModeSInterrogatorStatusBuilder::new()
1444    }
1445}
1446
1447impl From<u8> for ModeSInterrogatorStatus {
1448    fn from(record: u8) -> Self {
1449        const BITS_1_3: u8 = 0x70;
1450        let on_off_status = OnOffStatus::from((record & BIT_0_IN_BYTE) >> 7);
1451        let transmit_state = ModeSTransmitState::from((record & BITS_1_3) >> 4);
1452        let damage_status = DamageStatus::from((record & BIT_4_IN_BYTE) >> 3);
1453        let malfunction_status = MalfunctionStatus::from((record & BIT_5_IN_BYTE) >> 2);
1454
1455        ModeSInterrogatorStatus::builder()
1456            .with_on_off_status(on_off_status)
1457            .with_transmit_state(transmit_state)
1458            .with_damage_status(damage_status)
1459            .with_malfunction_status(malfunction_status)
1460            .build()
1461    }
1462}
1463
1464impl From<&ModeSInterrogatorStatus> for u8 {
1465    fn from(value: &ModeSInterrogatorStatus) -> Self {
1466        let on_off_status: u8 = u8::from(&value.on_off_status) << 7;
1467        let transmit_state: u8 = u8::from(value.transmit_state) << 4;
1468        let damage_status: u8 = u8::from(&value.damage_status) << 3;
1469        let malfunction_status: u8 = u8::from(&value.malfunction_status) << 2;
1470
1471        on_off_status | transmit_state | damage_status | malfunction_status
1472    }
1473}
1474
1475/// B.2.40 Mode S Levels Present record
1476#[derive(Clone, Default, Debug, PartialEq)]
1477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1478pub struct ModeSLevelsPresent {
1479    pub level_1: IffPresence,
1480    pub level_2_els: IffPresence,
1481    pub level_2_ehs: IffPresence,
1482    pub level_3: IffPresence,
1483    pub level_4: IffPresence,
1484}
1485
1486impl ModeSLevelsPresent {
1487    #[must_use]
1488    pub fn new() -> Self {
1489        ModeSLevelsPresent::default()
1490    }
1491
1492    #[must_use]
1493    pub fn builder() -> ModeSLevelsPresentBuilder {
1494        ModeSLevelsPresentBuilder::new()
1495    }
1496}
1497
1498impl From<u8> for ModeSLevelsPresent {
1499    #[allow(clippy::similar_names)]
1500    fn from(record: u8) -> Self {
1501        let level_1 = IffPresence::from((record & BIT_1_IN_BYTE) >> 6);
1502        let level_2_els = IffPresence::from((record & BIT_2_IN_BYTE) >> 5);
1503        let level_2_ehs = IffPresence::from((record & BIT_3_IN_BYTE) >> 4);
1504        let level_3 = IffPresence::from((record & BIT_4_IN_BYTE) >> 3);
1505        let level_4 = IffPresence::from((record & BIT_5_IN_BYTE) >> 2);
1506
1507        ModeSLevelsPresent::builder()
1508            .with_level_1(level_1)
1509            .with_level_2_ehs(level_2_ehs)
1510            .with_level_2_els(level_2_els)
1511            .with_level_3(level_3)
1512            .with_level_4(level_4)
1513            .build()
1514    }
1515}
1516
1517impl From<&ModeSLevelsPresent> for u8 {
1518    #[allow(clippy::similar_names)]
1519    fn from(value: &ModeSLevelsPresent) -> Self {
1520        let level_1: u8 = u8::from(&value.level_1) << 6;
1521        let level_2_els: u8 = u8::from(&value.level_2_els) << 5;
1522        let level_2_ehs: u8 = u8::from(&value.level_2_ehs) << 4;
1523        let level_3: u8 = u8::from(&value.level_3) << 3;
1524        let level_4: u8 = u8::from(&value.level_4) << 2;
1525
1526        level_1 | level_2_els | level_2_ehs | level_3 | level_4
1527    }
1528}
1529
1530/// Custom defined enum to model the presence of an element in an IFF system
1531#[derive(Clone, Default, Debug, PartialEq)]
1532#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1533pub enum IffPresence {
1534    #[default]
1535    NotPresent, // 0
1536    Present, // 1
1537}
1538
1539/// B.2.41 Mode S Transponder Basic Data record
1540#[derive(Clone, Default, Debug, PartialEq)]
1541#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1542pub struct ModeSTransponderBasicData {
1543    pub status: ModeSTransponderStatus,
1544    pub levels_present: ModeSLevelsPresent,
1545    pub aircraft_present_domain: AircraftPresentDomain,
1546    pub aircraft_identification: String, // B.2.35 - String of length 8, in ASCII.
1547    pub aircraft_address: u32,
1548    pub aircraft_identification_type: AircraftIdentificationType,
1549    pub dap_source: DapSource,   // B.2.6
1550    pub altitude: ModeSAltitude, // B.2.36
1551    pub capability_report: CapabilityReport,
1552}
1553
1554impl ModeSTransponderBasicData {
1555    #[must_use]
1556    pub fn new() -> Self {
1557        ModeSTransponderBasicData::default()
1558    }
1559
1560    #[must_use]
1561    pub fn builder() -> ModeSTransponderBasicDataBuilder {
1562        ModeSTransponderBasicDataBuilder::new()
1563    }
1564}
1565
1566/// B.2.42 Mode S Transponder Status record
1567#[derive(Clone, Default, Debug, PartialEq)]
1568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1569pub struct ModeSTransponderStatus {
1570    pub squitter_status: SquitterStatus,
1571    pub squitter_type: ModeSSquitterType,
1572    pub squitter_record_source: ModeSSquitterRecordSource,
1573    pub airborne_position_report_indicator: IffPresence,
1574    pub airborne_velocity_report_indicator: IffPresence,
1575    pub surface_position_report_indicator: IffPresence,
1576    pub identification_report_indicator: IffPresence,
1577    pub event_driven_report_indicator: IffPresence,
1578    pub on_off_status: OnOffStatus,
1579    pub damage_status: DamageStatus,
1580    pub malfunction_status: MalfunctionStatus,
1581}
1582
1583impl ModeSTransponderStatus {
1584    #[must_use]
1585    pub fn new() -> Self {
1586        ModeSTransponderStatus::default()
1587    }
1588
1589    #[must_use]
1590    pub fn builder() -> ModeSTransponderStatusBuilder {
1591        ModeSTransponderStatusBuilder::new()
1592    }
1593}
1594
1595impl From<u16> for ModeSTransponderStatus {
1596    fn from(record: u16) -> Self {
1597        const BIT_0: u16 = 0x8000;
1598        const BITS_1_3: u16 = 0x7000;
1599        const BIT_4: u16 = 0x800;
1600        const BIT_5: u16 = 0x400;
1601        const BIT_6: u16 = 0x200;
1602        const BIT_7: u16 = 0x100;
1603        const BIT_8: u16 = 0x80;
1604        const BIT_9: u16 = 0x40;
1605        const BIT_13: u16 = 0x04;
1606        const BIT_14: u16 = 0x02;
1607        const BIT_15: u16 = 0x01;
1608
1609        let squitter_status = SquitterStatus::from(((record & BIT_0) >> 15) as u8);
1610        let squitter_type = ModeSSquitterType::from(((record & BITS_1_3) >> 12) as u8);
1611        let squitter_record_source =
1612            ModeSSquitterRecordSource::from(((record & BIT_4) >> 11) as u8);
1613        let airborne_pos_ri = IffPresence::from(((record & BIT_5) >> 10) as u8);
1614        let airborne_vel_ri = IffPresence::from(((record & BIT_6) >> 9) as u8);
1615        let surface_pos_ri = IffPresence::from(((record & BIT_7) >> 8) as u8);
1616        let ident_ri = IffPresence::from(((record & BIT_8) >> 7) as u8);
1617        let event_driven_ri = IffPresence::from(((record & BIT_9) >> 6) as u8);
1618        let on_off_status = OnOffStatus::from(((record & BIT_13) >> 2) as u8);
1619        let damage_status = DamageStatus::from(((record & BIT_14) >> 1) as u8);
1620        let malfunction_status = MalfunctionStatus::from((record & BIT_15) as u8);
1621
1622        ModeSTransponderStatus::builder()
1623            .with_squitter_status(squitter_status)
1624            .with_squitter_type(squitter_type)
1625            .with_squitter_record_source(squitter_record_source)
1626            .with_airborne_position_report_indicator(airborne_pos_ri)
1627            .with_airborne_velocity_report_indicator(airborne_vel_ri)
1628            .with_surface_position_report_indicator(surface_pos_ri)
1629            .with_identification_report_indicator(ident_ri)
1630            .with_event_driven_report_indicator(event_driven_ri)
1631            .with_on_off_status(on_off_status)
1632            .with_damage_status(damage_status)
1633            .with_malfunction_status(malfunction_status)
1634            .build()
1635    }
1636}
1637
1638impl From<&ModeSTransponderStatus> for u16 {
1639    fn from(value: &ModeSTransponderStatus) -> Self {
1640        let squitter_status: u8 = u8::from(&value.squitter_status) << 7;
1641        let squitter_type: u8 = u8::from(value.squitter_type) << 4;
1642        let squitter_record_source: u8 = u8::from(value.squitter_record_source) << 3;
1643        let airborne_pos_ri: u8 = u8::from(&value.airborne_position_report_indicator) << 2;
1644        let airborne_vel_ri: u8 = u8::from(&value.airborne_velocity_report_indicator) << 1;
1645        let surface_pos_ri: u8 = u8::from(&value.surface_position_report_indicator);
1646        let byte_1 = u16::from(
1647            squitter_status
1648                | squitter_type
1649                | squitter_record_source
1650                | airborne_pos_ri
1651                | airborne_vel_ri
1652                | surface_pos_ri,
1653        );
1654
1655        let ident_ri: u8 = u8::from(&value.identification_report_indicator) << 7;
1656        let event_driven_ri: u8 = u8::from(&value.event_driven_report_indicator) << 6;
1657        let on_off_status: u8 = u8::from(&value.on_off_status) << 2;
1658        let damage_status: u8 = u8::from(&value.damage_status) << 1;
1659        let malfunction_status: u8 = u8::from(&value.malfunction_status);
1660        let byte_2 = u16::from(
1661            ident_ri | event_driven_ri | on_off_status | damage_status | malfunction_status,
1662        );
1663
1664        (byte_1 << 8) | byte_2
1665    }
1666}
1667
1668/// Custom defined enum to model the `SquitterStatus`
1669#[derive(Clone, Default, Debug, PartialEq)]
1670#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1671pub enum SquitterStatus {
1672    #[default]
1673    Off, // 0
1674    On, // 1
1675}
1676
1677/// B.2.52 System Status record
1678#[derive(Copy, Clone, Default, Debug, PartialEq)]
1679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1680pub struct SystemStatus {
1681    pub system_on_off_status: OnOffStatus,
1682    pub parameter_1_capable: ParameterCapable,
1683    pub parameter_2_capable: ParameterCapable,
1684    pub parameter_3_capable: ParameterCapable,
1685    pub parameter_4_capable: ParameterCapable,
1686    pub parameter_5_capable: ParameterCapable,
1687    pub parameter_6_capable: ParameterCapable,
1688    pub operational_status: OperationalStatus,
1689}
1690
1691impl SystemStatus {
1692    #[must_use]
1693    pub fn new() -> Self {
1694        SystemStatus::default()
1695    }
1696
1697    #[must_use]
1698    pub fn builder() -> SystemStatusBuilder {
1699        SystemStatusBuilder::new()
1700    }
1701}
1702
1703impl From<u8> for SystemStatus {
1704    fn from(record: u8) -> Self {
1705        let system_on_off_status = OnOffStatus::from((record & BIT_0_IN_BYTE) >> 7);
1706        let parameter_1_capable = ParameterCapable::from((record & BIT_1_IN_BYTE) >> 6);
1707        let parameter_2_capable = ParameterCapable::from((record & BIT_2_IN_BYTE) >> 5);
1708        let parameter_3_capable = ParameterCapable::from((record & BIT_3_IN_BYTE) >> 4);
1709        let parameter_4_capable = ParameterCapable::from((record & BIT_4_IN_BYTE) >> 3);
1710        let parameter_5_capable = ParameterCapable::from((record & BIT_5_IN_BYTE) >> 2);
1711        let parameter_6_capable = ParameterCapable::from((record & BIT_6_IN_BYTE) >> 1);
1712        let operational_status = OperationalStatus::from(record & BIT_7_IN_BYTE);
1713
1714        SystemStatus::builder()
1715            .with_system_on_off_status(system_on_off_status)
1716            .with_parameter_1_capable(parameter_1_capable)
1717            .with_parameter_2_capable(parameter_2_capable)
1718            .with_parameter_3_capable(parameter_3_capable)
1719            .with_parameter_4_capable(parameter_4_capable)
1720            .with_parameter_5_capable(parameter_5_capable)
1721            .with_parameter_6_capable(parameter_6_capable)
1722            .with_operational_status(operational_status)
1723            .build()
1724    }
1725}
1726
1727impl From<&SystemStatus> for u8 {
1728    fn from(value: &SystemStatus) -> Self {
1729        let system_on_off_status = u8::from(&value.system_on_off_status) << 7;
1730        let parameter_1 = u8::from(&value.parameter_1_capable) << 6;
1731        let parameter_2 = u8::from(&value.parameter_2_capable) << 5;
1732        let parameter_3 = u8::from(&value.parameter_3_capable) << 4;
1733        let parameter_4 = u8::from(&value.parameter_4_capable) << 3;
1734        let parameter_5 = u8::from(&value.parameter_5_capable) << 2;
1735        let parameter_6 = u8::from(&value.parameter_6_capable) << 1;
1736        let operational_status = u8::from(&value.operational_status);
1737
1738        system_on_off_status
1739            | parameter_1
1740            | parameter_2
1741            | parameter_3
1742            | parameter_4
1743            | parameter_5
1744            | parameter_6
1745            | operational_status
1746    }
1747}