dis_rs/common/attribute/
model.rs

1use crate::common::attribute::builder::AttributeBuilder;
2use crate::common::model::{EntityId, PduBody, SimulationAddress};
3use crate::common::{BodyInfo, Interaction};
4use crate::enumerations::{AttributeActionCode, PduType, ProtocolVersion, VariableRecordType};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8pub const BASE_ATTRIBUTE_BODY_LENGTH: u16 = 20;
9pub const BASE_ATTRIBUTE_RECORD_SET_LENGTH: u16 = 8;
10pub const BASE_ATTRIBUTE_RECORD_LENGTH_OCTETS: u16 = 6;
11
12/// 5.3.6 Attribute PDU
13///
14/// 7.2.6 Attribute PDU
15#[derive(Clone, Debug, Default, PartialEq)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct Attribute {
18    pub originating_simulation_address: SimulationAddress,
19    pub record_pdu_type: PduType,
20    pub record_protocol_version: ProtocolVersion,
21    pub master_attribute_record_type: VariableRecordType,
22    pub action_code: AttributeActionCode,
23    pub attribute_record_sets: Vec<AttributeRecordSet>,
24}
25
26impl Attribute {
27    #[must_use]
28    pub fn builder() -> AttributeBuilder {
29        AttributeBuilder::new()
30    }
31
32    #[must_use]
33    pub fn into_builder(self) -> AttributeBuilder {
34        AttributeBuilder::new_from_body(self)
35    }
36
37    #[must_use]
38    pub fn into_pdu_body(self) -> PduBody {
39        PduBody::Attribute(self)
40    }
41}
42
43impl BodyInfo for Attribute {
44    fn body_length(&self) -> u16 {
45        BASE_ATTRIBUTE_BODY_LENGTH
46            + self
47                .attribute_record_sets
48                .iter()
49                .map(|set| {
50                    BASE_ATTRIBUTE_RECORD_SET_LENGTH
51                        + set
52                            .attribute_records
53                            .iter()
54                            .map(|record| {
55                                BASE_ATTRIBUTE_RECORD_LENGTH_OCTETS
56                                    + record.specific_fields.len() as u16
57                            })
58                            .sum::<u16>()
59                })
60                .sum::<u16>()
61    }
62
63    fn body_type(&self) -> PduType {
64        PduType::Attribute
65    }
66}
67
68impl Interaction for Attribute {
69    fn originator(&self) -> Option<&EntityId> {
70        None
71    }
72
73    fn receiver(&self) -> Option<&EntityId> {
74        None
75    }
76}
77
78/// 5.3.6.3
79#[derive(Clone, Debug, PartialEq)]
80#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
81pub struct AttributeRecordSet {
82    pub entity_id: EntityId,
83    pub attribute_records: Vec<AttributeRecord>,
84}
85
86impl Default for AttributeRecordSet {
87    fn default() -> Self {
88        Self::new()
89    }
90}
91
92impl AttributeRecordSet {
93    #[must_use]
94    pub fn new() -> Self {
95        Self {
96            entity_id: EntityId::default(),
97            attribute_records: vec![],
98        }
99    }
100
101    #[must_use]
102    pub fn with_entity_id(mut self, entity_id: EntityId) -> Self {
103        self.entity_id = entity_id;
104        self
105    }
106
107    #[must_use]
108    pub fn with_attribute_records(mut self, attribute_records: Vec<AttributeRecord>) -> Self {
109        self.attribute_records = attribute_records;
110        self
111    }
112
113    #[must_use]
114    pub fn with_attribute_record(mut self, attribute_record: AttributeRecord) -> Self {
115        self.attribute_records.push(attribute_record);
116        self
117    }
118}
119
120/// 6.2.10 Attribute record
121#[derive(Clone, Debug, PartialEq)]
122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
123pub struct AttributeRecord {
124    pub record_type: VariableRecordType,
125    pub specific_fields: Vec<u8>,
126}
127
128impl Default for AttributeRecord {
129    fn default() -> Self {
130        Self::new()
131    }
132}
133
134impl AttributeRecord {
135    #[must_use]
136    pub fn new() -> Self {
137        Self {
138            record_type: VariableRecordType::default(),
139            specific_fields: vec![],
140        }
141    }
142
143    #[must_use]
144    pub fn with_record_type(mut self, record_type: VariableRecordType) -> Self {
145        self.record_type = record_type;
146        self
147    }
148
149    #[must_use]
150    pub fn with_specific_fields(mut self, specific_fields: Vec<u8>) -> Self {
151        self.specific_fields = specific_fields;
152        self
153    }
154}