1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, Element, EnumItem, IdentifiableAbstractionElement,
3 abstraction_element,
4 datatype::{self, DataTypeMap},
5 get_reference_parents, is_used,
6 software_component::{ArgumentDataPrototype, ParameterDataPrototype, VariableDataPrototype},
7};
8use autosar_data::ElementName;
9use datatype::{AbstractAutosarDataType, CompuMethod, DataConstr, SwBaseType};
10use std::fmt::Display;
11
12pub trait AbstractImplementationDataType: IdentifiableAbstractionElement {
14 fn category(&self) -> Option<ImplementationDataCategory> {
16 self.element()
17 .get_sub_element(ElementName::Category)?
18 .character_data()?
19 .string_value()?
20 .as_str()
21 .try_into()
22 .ok()
23 }
24
25 fn sub_elements(&self) -> impl Iterator<Item = ImplementationDataTypeElement> + Send + use<Self> {
27 self.element()
28 .get_sub_element(ElementName::SubElements)
29 .into_iter()
30 .flat_map(|elem| elem.sub_elements())
31 .filter_map(|elem| ImplementationDataTypeElement::try_from(elem).ok())
32 }
33
34 fn base_type(&self) -> Option<SwBaseType> {
36 let category = self.category()?;
37 if category != ImplementationDataCategory::Value {
38 return None;
39 }
40 self.element()
41 .get_sub_element(ElementName::SwDataDefProps)?
42 .get_sub_element(ElementName::SwDataDefPropsVariants)?
43 .get_sub_element(ElementName::SwDataDefPropsConditional)?
44 .get_sub_element(ElementName::BaseTypeRef)?
45 .get_reference_target()
46 .ok()?
47 .try_into()
48 .ok()
49 }
50
51 fn compu_method(&self) -> Option<CompuMethod> {
53 let category = self.category()?;
54 if category != ImplementationDataCategory::Value && category != ImplementationDataCategory::TypeReference {
55 return None;
56 }
57 self.element()
58 .get_sub_element(ElementName::SwDataDefProps)?
59 .get_sub_element(ElementName::SwDataDefPropsVariants)?
60 .get_sub_element(ElementName::SwDataDefPropsConditional)?
61 .get_sub_element(ElementName::CompuMethodRef)
62 .and_then(|cmref| cmref.get_reference_target().ok())
63 .and_then(|refelem| refelem.try_into().ok())
64 }
65
66 fn data_constraint(&self) -> Option<DataConstr> {
68 let category = self.category()?;
69 if category != ImplementationDataCategory::Value && category != ImplementationDataCategory::TypeReference {
70 return None;
71 }
72 self.element()
73 .get_sub_element(ElementName::SwDataDefProps)?
74 .get_sub_element(ElementName::SwDataDefPropsVariants)?
75 .get_sub_element(ElementName::SwDataDefPropsConditional)?
76 .get_sub_element(ElementName::DataConstrRef)
77 .and_then(|dcref| dcref.get_reference_target().ok())
78 .and_then(|refelem| refelem.try_into().ok())
79 }
80
81 fn referenced_type(&self) -> Option<ImplementationDataType> {
83 let category = self.category()?;
84 if category != ImplementationDataCategory::TypeReference {
85 return None;
86 }
87 self.element()
88 .get_sub_element(ElementName::SwDataDefProps)?
89 .get_sub_element(ElementName::SwDataDefPropsVariants)?
90 .get_sub_element(ElementName::SwDataDefPropsConditional)?
91 .get_sub_element(ElementName::ImplementationDataTypeRef)?
92 .get_reference_target()
93 .ok()?
94 .try_into()
95 .ok()
96 }
97
98 fn array_size(&self) -> Option<u32> {
100 let category = self.category()?;
101 if category != ImplementationDataCategory::Array {
102 return None;
103 }
104 self.sub_elements()
105 .next()?
106 .element()
107 .get_sub_element(ElementName::ArraySize)?
108 .character_data()?
109 .parse_integer()
110 }
111
112 fn data_pointer_target(&self) -> Option<DataPointerTarget> {
114 let category = self.category()?;
115 if category != ImplementationDataCategory::DataReference {
116 return None;
117 }
118 let sw_pointer_target_props = self
119 .element()
120 .get_sub_element(ElementName::SwDataDefProps)?
121 .get_sub_element(ElementName::SwDataDefPropsVariants)?
122 .get_sub_element(ElementName::SwDataDefPropsConditional)?
123 .get_sub_element(ElementName::SwPointerTargetProps)?
124 .get_sub_element(ElementName::SwDataDefProps)?
125 .get_sub_element(ElementName::SwDataDefPropsVariants)?
126 .get_sub_element(ElementName::SwDataDefPropsConditional)?;
127 if let Some(base_type) = sw_pointer_target_props
128 .get_sub_element(ElementName::BaseTypeRef)
129 .and_then(|elem| elem.get_reference_target().ok())
130 {
131 Some(DataPointerTarget::BaseType(base_type.try_into().ok()?))
132 } else if let Some(impl_data_type) = sw_pointer_target_props
133 .get_sub_element(ElementName::ImplementationDataTypeRef)
134 .and_then(|elem| elem.get_reference_target().ok())
135 {
136 Some(DataPointerTarget::ImplementationDataType(
137 impl_data_type.try_into().ok()?,
138 ))
139 } else {
140 None
141 }
142 }
143
144 fn apply_settings(&self, settings: &ImplementationDataTypeSettings) -> Result<(), AutosarAbstractionError> {
149 self.set_name(settings.name())?;
150 apply_impl_data_settings(self.element(), settings)
151 }
152
153 fn settings(&self) -> Option<ImplementationDataTypeSettings> {
155 let category = self.category()?;
156 match category {
157 ImplementationDataCategory::Value => Some(ImplementationDataTypeSettings::Value {
158 name: self.name()?,
159 base_type: self.base_type()?,
160 compu_method: self.compu_method(),
161 data_constraint: self.data_constraint(),
162 }),
163 ImplementationDataCategory::Array => {
164 let element_settings = self.sub_elements().next()?.settings()?;
165 Some(ImplementationDataTypeSettings::Array {
166 name: self.name()?,
167 length: self.array_size()?,
168 element_type: Box::new(element_settings),
169 })
170 }
171 ImplementationDataCategory::Structure => {
172 let elements = self
173 .sub_elements()
174 .map(|elem| elem.settings())
175 .collect::<Option<Vec<_>>>()?;
176 Some(ImplementationDataTypeSettings::Structure {
177 name: self.name()?,
178 elements,
179 })
180 }
181 ImplementationDataCategory::Union => {
182 let elements = self
183 .sub_elements()
184 .map(|elem| elem.settings())
185 .collect::<Option<Vec<_>>>()?;
186 Some(ImplementationDataTypeSettings::Union {
187 name: self.name()?,
188 elements,
189 })
190 }
191 ImplementationDataCategory::DataReference => {
192 let sw_pointer_target_props = self
193 .element()
194 .get_sub_element(ElementName::SwDataDefProps)?
195 .get_sub_element(ElementName::SwDataDefPropsVariants)?
196 .get_sub_element(ElementName::SwDataDefPropsConditional)?
197 .get_sub_element(ElementName::SwPointerTargetProps)?
198 .get_sub_element(ElementName::SwDataDefProps)?
199 .get_sub_element(ElementName::SwDataDefPropsVariants)?
200 .get_sub_element(ElementName::SwDataDefPropsConditional)?;
201 let target = if let Some(base_type) = sw_pointer_target_props
202 .get_sub_element(ElementName::BaseTypeRef)
203 .and_then(|elem| elem.get_reference_target().ok())
204 {
205 DataPointerTarget::BaseType(base_type.try_into().ok()?)
206 } else if let Some(impl_data_type) = sw_pointer_target_props
207 .get_sub_element(ElementName::ImplementationDataTypeRef)
208 .and_then(|elem| elem.get_reference_target().ok())
209 {
210 DataPointerTarget::ImplementationDataType(impl_data_type.try_into().ok()?)
211 } else {
212 return None;
213 };
214 Some(ImplementationDataTypeSettings::DataReference {
215 name: self.name()?,
216 target,
217 })
218 }
219 ImplementationDataCategory::FunctionReference => {
220 Some(ImplementationDataTypeSettings::FunctionReference { name: self.name()? })
221 }
222 ImplementationDataCategory::TypeReference => Some(ImplementationDataTypeSettings::TypeReference {
223 name: self.name()?,
224 reftype: self.referenced_type()?,
225 compu_method: self.compu_method(),
226 data_constraint: self.data_constraint(),
227 }),
228 }
229 }
230}
231
232#[derive(Debug, Clone, PartialEq, Eq, Hash)]
238pub struct ImplementationDataType(Element);
239abstraction_element!(ImplementationDataType, ImplementationDataType);
240impl IdentifiableAbstractionElement for ImplementationDataType {}
241impl AbstractAutosarDataType for ImplementationDataType {}
242impl AbstractImplementationDataType for ImplementationDataType {}
243
244impl ImplementationDataType {
245 pub(crate) fn new(
247 package: &ArPackage,
248 settings: &ImplementationDataTypeSettings,
249 ) -> Result<Self, AutosarAbstractionError> {
250 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
251 let implementation_data_type =
252 elements.create_named_sub_element(ElementName::ImplementationDataType, settings.name())?;
253 let implementation_data_type = Self(implementation_data_type);
254 implementation_data_type.apply_settings(settings)?;
255
256 Ok(implementation_data_type)
257 }
258
259 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
261 let opt_compu_method = self.compu_method();
262 let opt_data_constraint = self.data_constraint();
263 let opt_base_type = self.base_type();
264 let opt_referenced_type = self.referenced_type();
265
266 for element in self.sub_elements() {
267 element.remove(deep)?;
268 }
269
270 let ref_parents = get_reference_parents(self.element())?;
271
272 AbstractionElement::remove(self, deep)?;
273
274 for (named_parent, parent) in ref_parents {
275 match named_parent.element_name() {
276 ElementName::ImplementationDataType => {
277 if let Ok(impl_data_type) = ImplementationDataType::try_from(named_parent) {
278 impl_data_type.remove(deep)?;
279 }
280 }
281 ElementName::ImplementationDataTypeElement => {
282 if let Ok(impl_data_type_element) = ImplementationDataTypeElement::try_from(named_parent) {
283 impl_data_type_element.remove(deep)?;
284 }
285 }
286 ElementName::DataTypeMappingSet => {
287 if let Ok(datatype_map) = DataTypeMap::try_from(parent) {
288 datatype_map.remove(deep)?;
289 }
290 }
291 ElementName::ParameterDataPrototype => {
292 if let Ok(param_prototype) = ParameterDataPrototype::try_from(named_parent) {
293 param_prototype.remove(deep)?;
294 }
295 }
296 ElementName::VariableDataPrototype => {
297 if let Ok(var_prototype) = VariableDataPrototype::try_from(named_parent) {
298 var_prototype.remove(deep)?;
299 }
300 }
301 ElementName::ArgumentDataPrototype => {
302 if let Ok(arg_prototype) = ArgumentDataPrototype::try_from(named_parent) {
303 arg_prototype.remove(deep)?;
304 }
305 }
306 _ => {}
307 }
308 }
309
310 if deep {
311 if let Some(compu_method) = opt_compu_method
312 && !is_used(compu_method.element())
313 {
314 compu_method.remove(deep)?;
315 }
316 if let Some(data_constraint) = opt_data_constraint
317 && !is_used(data_constraint.element())
318 {
319 data_constraint.remove(deep)?;
320 }
321 if let Some(base_type) = opt_base_type
322 && !is_used(base_type.element())
323 {
324 base_type.remove(deep)?;
325 }
326 if let Some(referenced_type) = opt_referenced_type
327 && !is_used(referenced_type.element())
328 {
329 referenced_type.remove(deep)?;
330 }
331 }
332 Ok(())
333 }
334}
335
336#[derive(Debug, Clone, PartialEq, Eq, Hash)]
340pub struct ImplementationDataTypeElement(Element);
341abstraction_element!(ImplementationDataTypeElement, ImplementationDataTypeElement);
342impl IdentifiableAbstractionElement for ImplementationDataTypeElement {}
343impl AbstractImplementationDataType for ImplementationDataTypeElement {}
344
345impl ImplementationDataTypeElement {
346 pub(crate) fn new(
347 parent: &Element,
348 settings: &ImplementationDataTypeSettings,
349 ) -> Result<Self, AutosarAbstractionError> {
350 let implementation_data_type_element =
351 parent.create_named_sub_element(ElementName::ImplementationDataTypeElement, settings.name())?;
352 let implementation_data_type_element = Self(implementation_data_type_element);
353 implementation_data_type_element.apply_settings(settings)?;
354
355 Ok(implementation_data_type_element)
356 }
357
358 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
360 let opt_compu_method = self.compu_method();
361 let opt_data_constraint = self.data_constraint();
362 let opt_base_type = self.base_type();
363 let opt_referenced_type = self.referenced_type();
364
365 for element in self.sub_elements() {
366 element.remove(deep)?;
367 }
368
369 AbstractionElement::remove(self, deep)?;
370
371 if deep {
372 if let Some(compu_method) = opt_compu_method
373 && !is_used(compu_method.element())
374 {
375 compu_method.remove(deep)?;
376 }
377 if let Some(data_constraint) = opt_data_constraint
378 && !is_used(data_constraint.element())
379 {
380 data_constraint.remove(deep)?;
381 }
382 if let Some(base_type) = opt_base_type
383 && !is_used(base_type.element())
384 {
385 base_type.remove(deep)?;
386 }
387 if let Some(referenced_type) = opt_referenced_type
388 && !is_used(referenced_type.element())
389 {
390 referenced_type.remove(deep)?;
391 }
392 }
393
394 Ok(())
395 }
396}
397
398fn apply_impl_data_settings(
401 element: &Element,
402 settings: &ImplementationDataTypeSettings,
403) -> Result<(), AutosarAbstractionError> {
404 let _ = element.remove_sub_element_kind(ElementName::Category);
406 let _ = element.remove_sub_element_kind(ElementName::SubElements);
407 let _ = element.remove_sub_element_kind(ElementName::SwDataDefProps);
408 let _ = element.remove_sub_element_kind(ElementName::DynamicArraySizeProfile);
410
411 match settings {
412 ImplementationDataTypeSettings::Value {
413 base_type,
414 compu_method,
415 data_constraint,
416 ..
417 } => {
418 element
419 .create_sub_element(ElementName::Category)?
420 .set_character_data("VALUE")?;
421 let sw_data_def_props = element
422 .create_sub_element(ElementName::SwDataDefProps)?
423 .create_sub_element(ElementName::SwDataDefPropsVariants)?
424 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
425 sw_data_def_props
426 .create_sub_element(ElementName::BaseTypeRef)?
427 .set_reference_target(base_type.element())?;
428 if let Some(compu_method) = compu_method {
429 sw_data_def_props
430 .create_sub_element(ElementName::CompuMethodRef)?
431 .set_reference_target(compu_method.element())?;
432 }
433 if let Some(data_constraint) = data_constraint {
434 sw_data_def_props
435 .create_sub_element(ElementName::DataConstrRef)?
436 .set_reference_target(data_constraint.element())?;
437 }
438 }
439 ImplementationDataTypeSettings::Array {
440 length, element_type, ..
441 } => {
442 element
443 .create_sub_element(ElementName::Category)?
444 .set_character_data("ARRAY")?;
445 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
446 let array_element = ImplementationDataTypeElement::new(&sub_elements, element_type)?;
447 array_element
448 .element()
449 .create_sub_element(ElementName::ArraySize)?
450 .set_character_data(u64::from(*length))?;
451 array_element
452 .element()
453 .create_sub_element(ElementName::ArraySizeSemantics)?
454 .set_character_data(EnumItem::FixedSize)?;
455 }
456 ImplementationDataTypeSettings::Structure { elements, .. } => {
457 element
458 .create_sub_element(ElementName::Category)?
459 .set_character_data("STRUCTURE")?;
460 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
461 for sub_element in elements {
462 ImplementationDataTypeElement::new(&sub_elements, sub_element)?;
463 }
464 }
465 ImplementationDataTypeSettings::Union { elements, .. } => {
466 element
467 .create_sub_element(ElementName::Category)?
468 .set_character_data("UNION")?;
469 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
470 for sub_element in elements {
471 ImplementationDataTypeElement::new(&sub_elements, sub_element)?;
472 }
473 }
474 ImplementationDataTypeSettings::DataReference { target, .. } => {
475 element
476 .create_sub_element(ElementName::Category)?
477 .set_character_data("DATA_REFERENCE")?;
478 let pointer_props = element
479 .create_sub_element(ElementName::SwDataDefProps)?
480 .create_sub_element(ElementName::SwDataDefPropsVariants)?
481 .create_sub_element(ElementName::SwDataDefPropsConditional)?
482 .create_sub_element(ElementName::SwPointerTargetProps)?;
483 let contained_props = pointer_props
484 .create_sub_element(ElementName::SwDataDefProps)?
485 .create_sub_element(ElementName::SwDataDefPropsVariants)?
486 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
487 match target {
488 DataPointerTarget::BaseType(base_type) => {
489 contained_props
490 .create_sub_element(ElementName::BaseTypeRef)?
491 .set_reference_target(base_type.element())?;
492 pointer_props
493 .create_sub_element(ElementName::TargetCategory)
494 .and_then(|elem| elem.set_character_data("VALUE"))?;
495 }
496 DataPointerTarget::ImplementationDataType(impl_data_type) => {
497 contained_props
498 .create_sub_element(ElementName::ImplementationDataTypeRef)?
499 .set_reference_target(impl_data_type.element())?;
500 let target_category = impl_data_type
501 .category()
502 .as_ref()
503 .map(|item| item.to_string())
504 .unwrap_or("VALUE".to_string());
505 pointer_props
506 .create_sub_element(ElementName::TargetCategory)?
507 .set_character_data(target_category)?;
508 }
509 }
510 }
511 ImplementationDataTypeSettings::FunctionReference { .. } => {
512 element
513 .create_sub_element(ElementName::Category)?
514 .set_character_data("FUNCTION_REFERENCE")?;
515 }
516 ImplementationDataTypeSettings::TypeReference {
517 reftype,
518 compu_method,
519 data_constraint,
520 ..
521 } => {
522 element
523 .create_sub_element(ElementName::Category)?
524 .set_character_data("TYPE_REFERENCE")?;
525 let sw_data_def_props = element
526 .create_sub_element(ElementName::SwDataDefProps)?
527 .create_sub_element(ElementName::SwDataDefPropsVariants)?
528 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
529 sw_data_def_props
530 .create_sub_element(ElementName::ImplementationDataTypeRef)?
531 .set_reference_target(reftype.element())?;
532 if let Some(compu_method) = compu_method {
533 sw_data_def_props
534 .create_sub_element(ElementName::CompuMethodRef)?
535 .set_reference_target(compu_method.element())?;
536 }
537 if let Some(data_constraint) = data_constraint {
538 sw_data_def_props
539 .create_sub_element(ElementName::DataConstrRef)?
540 .set_reference_target(data_constraint.element())?;
541 }
542 }
543 }
544
545 Ok(())
546}
547
548#[derive(Debug, Clone, PartialEq, Eq, Hash)]
552pub enum ImplementationDataCategory {
553 Value,
555 DataReference,
557 FunctionReference,
559 TypeReference,
561 Structure,
563 Union,
565 Array,
567}
568
569impl Display for ImplementationDataCategory {
570 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
571 match self {
572 ImplementationDataCategory::Value => f.write_str("VALUE"),
573 ImplementationDataCategory::DataReference => f.write_str("DATA_REFERENCE"),
574 ImplementationDataCategory::FunctionReference => f.write_str("FUNCTION_REFERENCE"),
575 ImplementationDataCategory::TypeReference => f.write_str("TYPE_REFERENCE"),
576 ImplementationDataCategory::Structure => f.write_str("STRUCTURE"),
577 ImplementationDataCategory::Union => f.write_str("UNION"),
578 ImplementationDataCategory::Array => f.write_str("ARRAY"),
579 }
580 }
581}
582
583impl TryFrom<&str> for ImplementationDataCategory {
584 type Error = AutosarAbstractionError;
585
586 fn try_from(value: &str) -> Result<Self, Self::Error> {
587 match value {
588 "VALUE" => Ok(ImplementationDataCategory::Value),
589 "DATA_REFERENCE" => Ok(ImplementationDataCategory::DataReference),
590 "FUNCTION_REFERENCE" => Ok(ImplementationDataCategory::FunctionReference),
591 "TYPE_REFERENCE" => Ok(ImplementationDataCategory::TypeReference),
592 "STRUCTURE" => Ok(ImplementationDataCategory::Structure),
593 "UNION" => Ok(ImplementationDataCategory::Union),
594 "ARRAY" => Ok(ImplementationDataCategory::Array),
595 _ => Err(AutosarAbstractionError::ValueConversionError {
596 value: value.to_string(),
597 dest: "ImplementationDataCategory".to_string(),
598 }),
599 }
600 }
601}
602
603#[derive(Debug, Clone, PartialEq, Eq, Hash)]
609pub enum ImplementationDataTypeSettings {
610 Value {
612 name: String,
614 base_type: SwBaseType,
616 compu_method: Option<CompuMethod>,
618 data_constraint: Option<DataConstr>,
620 },
621 Array {
623 name: String,
625 length: u32,
627 element_type: Box<ImplementationDataTypeSettings>,
629 },
630 Structure {
632 name: String,
634 elements: Vec<ImplementationDataTypeSettings>,
636 },
637 Union {
639 name: String,
641 elements: Vec<ImplementationDataTypeSettings>,
643 },
644 DataReference {
646 name: String,
648 target: DataPointerTarget,
650 },
651 FunctionReference {
653 name: String,
655 },
657 TypeReference {
659 name: String,
661 reftype: ImplementationDataType,
663 compu_method: Option<CompuMethod>,
665 data_constraint: Option<DataConstr>,
667 },
668}
669
670impl ImplementationDataTypeSettings {
671 #[must_use]
673 pub fn name(&self) -> &str {
674 match self {
675 ImplementationDataTypeSettings::Value { name, .. } => name,
676 ImplementationDataTypeSettings::Array { name, .. } => name,
677 ImplementationDataTypeSettings::Structure { name, .. } => name,
678 ImplementationDataTypeSettings::Union { name, .. } => name,
679 ImplementationDataTypeSettings::DataReference { name, .. } => name,
680 ImplementationDataTypeSettings::FunctionReference { name, .. } => name,
681 ImplementationDataTypeSettings::TypeReference { name, .. } => name,
682 }
683 }
684}
685
686#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690pub enum DataPointerTarget {
691 BaseType(SwBaseType),
693 ImplementationDataType(ImplementationDataType),
695}
696
697#[cfg(test)]
700mod tests {
701 use super::*;
702 use crate::{
703 AutosarModelAbstraction,
704 datatype::{ApplicationArraySize, ApplicationPrimitiveCategory},
705 software_component::ArgumentDirection,
706 };
707 use autosar_data::AutosarVersion;
708 use datatype::{BaseTypeEncoding, CompuMethodLinearContent, CompuScaleDirection};
709
710 #[test]
711 fn test_impl_data_type() {
712 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
713 let package = model.get_or_create_package("/DataTypes").unwrap();
714 let base_type =
715 SwBaseType::new("uint8", &package, 8, BaseTypeEncoding::None, None, None, Some("uint8")).unwrap();
716 let compu_method = CompuMethod::new(
717 "linear",
718 &package,
719 datatype::CompuMethodContent::Linear(CompuMethodLinearContent {
720 direction: CompuScaleDirection::IntToPhys,
721 offset: 42.0,
722 factor: 1.0,
723 divisor: 1.0,
724 lower_limit: None,
725 upper_limit: None,
726 }),
727 )
728 .unwrap();
729 let data_constraint = DataConstr::new("constraint", &package).unwrap();
730 let other_impl_data_type = ImplementationDataType::new(
731 &package,
732 &ImplementationDataTypeSettings::Value {
733 name: "OtherImplDataType".to_string(),
734 base_type: base_type.clone(),
735 compu_method: Some(compu_method.clone()),
736 data_constraint: None,
737 },
738 )
739 .unwrap();
740 let settings = ImplementationDataTypeSettings::Structure {
741 name: "Structure".to_string(),
742 elements: vec![
743 ImplementationDataTypeSettings::Union {
744 name: "union".to_string(),
745 elements: vec![ImplementationDataTypeSettings::Value {
746 name: "MyImplDataType1".to_string(),
747 base_type: base_type.clone(),
748 compu_method: Some(compu_method.clone()),
749 data_constraint: Some(data_constraint.clone()),
750 }],
751 },
752 ImplementationDataTypeSettings::Value {
753 name: "MyImplDataType1".to_string(),
754 base_type: base_type.clone(),
755 compu_method: Some(compu_method.clone()),
756 data_constraint: Some(data_constraint.clone()),
757 },
758 ImplementationDataTypeSettings::Array {
759 name: "MyArray".to_string(),
760 length: 10,
761 element_type: Box::new(ImplementationDataTypeSettings::Value {
762 name: "MyImplDataType2".to_string(),
763 base_type: base_type.clone(),
764 compu_method: Some(compu_method.clone()),
765 data_constraint: None,
766 }),
767 },
768 ImplementationDataTypeSettings::TypeReference {
769 name: "ReferenceType".to_string(),
770 reftype: other_impl_data_type.clone(),
771 compu_method: Some(compu_method.clone()),
772 data_constraint: Some(data_constraint.clone()),
773 },
774 ImplementationDataTypeSettings::DataReference {
775 name: "DataReferenceToBase".to_string(),
776 target: DataPointerTarget::BaseType(base_type.clone()),
777 },
778 ImplementationDataTypeSettings::DataReference {
779 name: "DataReferenceToImpl".to_string(),
780 target: DataPointerTarget::ImplementationDataType(other_impl_data_type.clone()),
781 },
782 ],
783 };
784 let impl_data_type = ImplementationDataType::new(&package, &settings).unwrap();
785
786 assert_eq!(impl_data_type.category(), Some(ImplementationDataCategory::Structure));
787
788 let sub_elements = impl_data_type.sub_elements().collect::<Vec<_>>();
789 assert_eq!(sub_elements.len(), 6);
790 assert_eq!(sub_elements[0].category(), Some(ImplementationDataCategory::Union));
791 assert_eq!(sub_elements[1].category(), Some(ImplementationDataCategory::Value));
792 assert_eq!(sub_elements[2].category(), Some(ImplementationDataCategory::Array));
793 assert_eq!(
794 sub_elements[3].category(),
795 Some(ImplementationDataCategory::TypeReference)
796 );
797 assert_eq!(
798 sub_elements[4].category(),
799 Some(ImplementationDataCategory::DataReference)
800 );
801 assert_eq!(
802 sub_elements[4].data_pointer_target(),
803 Some(DataPointerTarget::BaseType(base_type.clone()))
804 );
805 assert_eq!(
806 sub_elements[5].category(),
807 Some(ImplementationDataCategory::DataReference)
808 );
809 assert_eq!(
810 sub_elements[5].data_pointer_target(),
811 Some(DataPointerTarget::ImplementationDataType(other_impl_data_type.clone()))
812 );
813
814 let settings_read = impl_data_type.settings().unwrap();
815 assert_eq!(settings, settings_read);
816
817 let settings2 = ImplementationDataTypeSettings::Value {
819 name: "NewImplDataType".to_string(),
820 base_type,
821 compu_method: None,
822 data_constraint: None,
823 };
824 impl_data_type.apply_settings(&settings2).unwrap();
825 let settings_read = impl_data_type.settings().unwrap();
826 assert_eq!(settings2, settings_read);
827 }
828
829 #[test]
830 fn implementation_data_category() {
831 assert_eq!(ImplementationDataCategory::Value.to_string(), "VALUE");
832 assert_eq!(ImplementationDataCategory::DataReference.to_string(), "DATA_REFERENCE");
833 assert_eq!(
834 ImplementationDataCategory::FunctionReference.to_string(),
835 "FUNCTION_REFERENCE"
836 );
837 assert_eq!(ImplementationDataCategory::TypeReference.to_string(), "TYPE_REFERENCE");
838 assert_eq!(ImplementationDataCategory::Structure.to_string(), "STRUCTURE");
839 assert_eq!(ImplementationDataCategory::Union.to_string(), "UNION");
840 assert_eq!(ImplementationDataCategory::Array.to_string(), "ARRAY");
841
842 assert_eq!(
843 ImplementationDataCategory::try_from("VALUE").unwrap(),
844 ImplementationDataCategory::Value
845 );
846 assert_eq!(
847 ImplementationDataCategory::try_from("DATA_REFERENCE").unwrap(),
848 ImplementationDataCategory::DataReference
849 );
850 assert_eq!(
851 ImplementationDataCategory::try_from("FUNCTION_REFERENCE").unwrap(),
852 ImplementationDataCategory::FunctionReference
853 );
854 assert_eq!(
855 ImplementationDataCategory::try_from("TYPE_REFERENCE").unwrap(),
856 ImplementationDataCategory::TypeReference
857 );
858 assert_eq!(
859 ImplementationDataCategory::try_from("STRUCTURE").unwrap(),
860 ImplementationDataCategory::Structure
861 );
862 assert_eq!(
863 ImplementationDataCategory::try_from("UNION").unwrap(),
864 ImplementationDataCategory::Union
865 );
866 assert_eq!(
867 ImplementationDataCategory::try_from("ARRAY").unwrap(),
868 ImplementationDataCategory::Array
869 );
870
871 assert!(ImplementationDataCategory::try_from("invalid").is_err());
872 }
873
874 #[test]
875 fn remove() {
876 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
877 let package = model.get_or_create_package("/DataTypes").unwrap();
878 let element_type = package
879 .create_application_primitive_data_type(
880 "AppPrimitive",
881 ApplicationPrimitiveCategory::Value,
882 None,
883 None,
884 None,
885 )
886 .unwrap();
887 let array_data_type = package
888 .create_application_array_data_type("AppArray", &element_type, ApplicationArraySize::Fixed(10))
889 .unwrap();
890
891 let base_type = package
893 .create_sw_base_type("uint8", 8, BaseTypeEncoding::TwosComplement, None, None, Some("uint8"))
894 .unwrap();
895 let impl_array = package
896 .create_implementation_data_type(&ImplementationDataTypeSettings::Array {
897 name: "ImplArray".to_string(),
898 length: 10,
899 element_type: Box::new(ImplementationDataTypeSettings::Value {
900 name: "ImplPrimitive".to_string(),
901 base_type,
902 compu_method: None,
903 data_constraint: None,
904 }),
905 })
906 .unwrap();
907
908 let data_type_mapping_set = package.create_data_type_mapping_set("DataTypeMappingSet").unwrap();
910 data_type_mapping_set
911 .create_data_type_map(&impl_array, &array_data_type)
912 .unwrap();
913
914 let sr_interface = package.create_sender_receiver_interface("SRInterface").unwrap();
916 let _vdp = sr_interface.create_data_element("VDP", &impl_array).unwrap();
917 let cs_interface = package.create_client_server_interface("CSInterface").unwrap();
919 let cso = cs_interface.create_operation("ADP").unwrap();
920 let _adp = cso.create_argument("ADP", &impl_array, ArgumentDirection::In).unwrap();
921
922 let impl_ref_type = package
924 .create_implementation_data_type(&ImplementationDataTypeSettings::TypeReference {
925 name: "ImplRecord".to_string(),
926 reftype: impl_array.clone(),
927 compu_method: None,
928 data_constraint: None,
929 })
930 .unwrap();
931
932 impl_array.remove(true).unwrap();
934
935 assert_eq!(data_type_mapping_set.data_type_maps().count(), 0);
937 assert_eq!(sr_interface.data_elements().count(), 0);
938 assert_eq!(cso.arguments().count(), 0);
939 assert!(impl_ref_type.element().path().is_err());
940 }
941}