autosar_data_abstraction/datatype/
mod.rs1use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
7};
8use autosar_data::{Element, ElementName};
9
10mod applicationtype;
11mod basetype;
12mod compu_method;
13mod implementationtype;
14mod mapping;
15mod values;
16
17pub use applicationtype::*;
18pub use basetype::*;
19pub use compu_method::*;
20pub use implementationtype::*;
21pub use mapping::*;
22pub use values::*;
23
24pub trait AbstractAutosarDataType: AbstractionElement {}
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub enum AutosarDataType {
36 ApplicationPrimitiveDataType(ApplicationPrimitiveDataType),
38 ApplicationArrayDataType(ApplicationArrayDataType),
40 ApplicationRecordDataType(ApplicationRecordDataType),
42 ImplementationDataType(ImplementationDataType),
44}
45
46impl AbstractionElement for AutosarDataType {
47 fn element(&self) -> &Element {
48 match self {
49 AutosarDataType::ApplicationPrimitiveDataType(data_type) => data_type.element(),
50 AutosarDataType::ApplicationArrayDataType(data_type) => data_type.element(),
51 AutosarDataType::ApplicationRecordDataType(data_type) => data_type.element(),
52 AutosarDataType::ImplementationDataType(data_type) => data_type.element(),
53 }
54 }
55}
56
57impl TryFrom<Element> for AutosarDataType {
58 type Error = AutosarAbstractionError;
59
60 fn try_from(element: Element) -> Result<Self, Self::Error> {
61 match element.element_name() {
62 ElementName::ApplicationPrimitiveDataType => Ok(Self::ApplicationPrimitiveDataType(
63 ApplicationPrimitiveDataType::try_from(element)?,
64 )),
65 ElementName::ApplicationArrayDataType => Ok(Self::ApplicationArrayDataType(
66 ApplicationArrayDataType::try_from(element)?,
67 )),
68 ElementName::ApplicationRecordDataType => Ok(Self::ApplicationRecordDataType(
69 ApplicationRecordDataType::try_from(element)?,
70 )),
71 ElementName::ImplementationDataType => {
72 Ok(Self::ImplementationDataType(ImplementationDataType::try_from(element)?))
73 }
74 _ => Err(AutosarAbstractionError::ConversionError {
75 element,
76 dest: "AutosarDataType".to_string(),
77 }),
78 }
79 }
80}
81
82impl IdentifiableAbstractionElement for AutosarDataType {}
83impl AbstractAutosarDataType for AutosarDataType {}
84
85#[derive(Debug, Clone, PartialEq, Eq, Hash)]
91pub struct Unit(Element);
92abstraction_element!(Unit, Unit);
93impl IdentifiableAbstractionElement for Unit {}
94
95impl Unit {
96 pub(crate) fn new(
98 name: &str,
99 package: &ArPackage,
100 display_name: Option<&str>,
101 ) -> Result<Self, AutosarAbstractionError> {
102 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
103 let unit_elem = elements.create_named_sub_element(ElementName::Unit, name)?;
104 let unit = Unit(unit_elem);
105
106 unit.set_display_name(display_name)?;
107
108 Ok(unit)
109 }
110
111 pub fn set_display_name(&self, display_name: Option<&str>) -> Result<(), AutosarAbstractionError> {
113 if let Some(display_name) = display_name {
114 self.element()
115 .get_or_create_sub_element(ElementName::DisplayName)?
116 .set_character_data(display_name)?;
117 } else {
118 let _ = self.element().remove_sub_element_kind(ElementName::DisplayName);
119 }
120
121 Ok(())
122 }
123
124 #[must_use]
126 pub fn display_name(&self) -> Option<String> {
127 self.element()
128 .get_sub_element(ElementName::DisplayName)?
129 .character_data()?
130 .string_value()
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Hash)]
138pub struct DataConstr(Element);
139abstraction_element!(DataConstr, DataConstr);
140impl IdentifiableAbstractionElement for DataConstr {}
141
142impl DataConstr {
143 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
145 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
146 let data_constr = elements.create_named_sub_element(ElementName::DataConstr, name)?;
147
148 Ok(Self(data_constr))
149 }
150
151 pub fn create_data_constr_rule(
153 &self,
154 rule_type: DataConstrType,
155 lower_limit: Option<f64>,
156 upper_limit: Option<f64>,
157 ) -> Result<DataConstrRule, AutosarAbstractionError> {
158 let data_constr_rules = self.element().get_or_create_sub_element(ElementName::DataConstrRules)?;
159 let rule = DataConstrRule::new(&data_constr_rules, rule_type, lower_limit, upper_limit)?;
160 Ok(rule)
161 }
162
163 pub fn data_constr_rules(&self) -> impl Iterator<Item = DataConstrRule> + Send + use<> {
165 self.element()
166 .get_sub_element(ElementName::DataConstrRules)
167 .into_iter()
168 .flat_map(|rules| rules.sub_elements())
169 .filter_map(|elem| DataConstrRule::try_from(elem).ok())
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Hash)]
177pub struct DataConstrRule(Element);
178abstraction_element!(DataConstrRule, DataConstrRule);
179
180impl DataConstrRule {
181 pub(crate) fn new(
182 parent: &Element,
183 rule_type: DataConstrType,
184 lower_limit: Option<f64>,
185 upper_limit: Option<f64>,
186 ) -> Result<Self, AutosarAbstractionError> {
187 let rule = parent.create_sub_element(ElementName::DataConstrRule)?;
188 let constrs = match rule_type {
189 DataConstrType::Internal => rule.create_sub_element(ElementName::InternalConstrs)?,
190 DataConstrType::Physical => rule.create_sub_element(ElementName::PhysConstrs)?,
191 };
192
193 if let Some(lower_limit) = lower_limit {
194 constrs
195 .create_sub_element(ElementName::LowerLimit)?
196 .set_character_data(lower_limit)?;
197 }
198
199 if let Some(upper_limit) = upper_limit {
200 constrs
201 .create_sub_element(ElementName::UpperLimit)?
202 .set_character_data(upper_limit)?;
203 }
204
205 Ok(Self(rule))
206 }
207
208 #[must_use]
210 pub fn rule_type(&self) -> DataConstrType {
211 if self.element().get_sub_element(ElementName::InternalConstrs).is_some() {
212 DataConstrType::Internal
213 } else {
214 DataConstrType::Physical
215 }
216 }
217
218 #[must_use]
220 pub fn lower_limit(&self) -> Option<f64> {
221 self.element()
222 .get_sub_element(ElementName::InternalConstrs)
223 .or(self.element().get_sub_element(ElementName::PhysConstrs))?
224 .get_sub_element(ElementName::LowerLimit)?
225 .character_data()?
226 .parse_float()
227 }
228
229 #[must_use]
231 pub fn upper_limit(&self) -> Option<f64> {
232 self.element()
233 .get_sub_element(ElementName::InternalConstrs)
234 .or(self.element().get_sub_element(ElementName::PhysConstrs))?
235 .get_sub_element(ElementName::UpperLimit)?
236 .character_data()?
237 .parse_float()
238 }
239}
240
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
245pub enum DataConstrType {
246 Internal,
248 Physical,
250}
251
252#[cfg(test)]
255mod test {
256 use super::*;
257 use crate::AutosarModelAbstraction;
258 use autosar_data::AutosarVersion;
259
260 #[test]
261 fn unit() {
262 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
263 let package = model.get_or_create_package("/Units").unwrap();
264
265 let unit = Unit::new("Unit", &package, Some("Unit Display")).unwrap();
266 assert_eq!(unit.display_name(), Some("Unit Display".to_string()));
267 }
268
269 #[test]
270 fn data_constr() {
271 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
272 let package = model.get_or_create_package("/DataConstraints").unwrap();
273
274 let data_constr = DataConstr::new("DataConstr", &package).unwrap();
275
276 let rule1 = data_constr
277 .create_data_constr_rule(DataConstrType::Internal, Some(1.0), Some(100.0))
278 .unwrap();
279 assert_eq!(rule1.rule_type(), DataConstrType::Internal);
280 assert_eq!(rule1.lower_limit(), Some(1.0));
281 assert_eq!(rule1.upper_limit(), Some(100.0));
282
283 let rule2 = data_constr
284 .create_data_constr_rule(DataConstrType::Physical, Some(2.0), Some(200.0))
285 .unwrap();
286 assert_eq!(rule2.rule_type(), DataConstrType::Physical);
287 assert_eq!(rule2.lower_limit(), Some(2.0));
288 assert_eq!(rule2.upper_limit(), Some(200.0));
289
290 let rules = data_constr.data_constr_rules().collect::<Vec<_>>();
291 assert_eq!(rules.len(), 2);
292 }
293
294 #[test]
295 fn autosar_data_type() {
296 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
297 let package = model.get_or_create_package("/DataTypes").unwrap();
298
299 let app_primitive = ApplicationPrimitiveDataType::new(
300 "Primitive",
301 &package,
302 ApplicationPrimitiveCategory::Value,
303 None,
304 None,
305 None,
306 )
307 .unwrap();
308 let app_array =
309 ApplicationArrayDataType::new("Array", &package, &app_primitive, ApplicationArraySize::Fixed(1)).unwrap();
310 let app_record = ApplicationRecordDataType::new("Record", &package).unwrap();
311 let base_type =
312 SwBaseType::new("uint8", &package, 8, BaseTypeEncoding::None, None, None, Some("uint8")).unwrap();
313 let impl_settings = ImplementationDataTypeSettings::Value {
314 name: "ImplValue".to_string(),
315 base_type: base_type.clone(),
316 compu_method: None,
317 data_constraint: None,
318 };
319 let impl_type = ImplementationDataType::new(&package, &impl_settings).unwrap();
320
321 let app_primitive2 = AutosarDataType::try_from(app_primitive.element().clone()).unwrap();
322 assert!(matches!(
323 app_primitive2,
324 AutosarDataType::ApplicationPrimitiveDataType(_)
325 ));
326 assert_eq!(app_primitive2.element(), app_primitive.element());
327
328 let app_array2 = AutosarDataType::try_from(app_array.element().clone()).unwrap();
329 assert!(matches!(app_array2, AutosarDataType::ApplicationArrayDataType(_)));
330 assert_eq!(app_array2.element(), app_array.element());
331
332 let app_record2 = AutosarDataType::try_from(app_record.element().clone()).unwrap();
333 assert!(matches!(app_record2, AutosarDataType::ApplicationRecordDataType(_)));
334 assert_eq!(app_record2.element(), app_record.element());
335
336 let impl_type2 = AutosarDataType::try_from(impl_type.element().clone()).unwrap();
337 assert!(matches!(impl_type2, AutosarDataType::ImplementationDataType(_)));
338 assert_eq!(impl_type2.element(), impl_type.element());
339 }
340}