1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, Element, 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, EnumItem};
9use datatype::{AbstractAutosarDataType, CompuMethod, DataConstr, Unit};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
17pub struct ApplicationArrayDataType(Element);
18abstraction_element!(ApplicationArrayDataType, ApplicationArrayDataType);
19impl IdentifiableAbstractionElement for ApplicationArrayDataType {}
20impl AbstractAutosarDataType for ApplicationArrayDataType {}
21
22impl ApplicationArrayDataType {
23 pub(crate) fn new<T: Into<ApplicationDataType> + AbstractionElement>(
25 name: &str,
26 package: &ArPackage,
27 element_type: &T,
28 size: ApplicationArraySize,
29 ) -> Result<Self, AutosarAbstractionError> {
30 let element_type = element_type.clone().into();
31 Self::new_internal(name, package, &element_type, size)
32 }
33
34 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
36 if let Some(array_element) = self.array_element() {
37 array_element.remove(deep)?;
38 }
39 let ref_parents = get_reference_parents(self.element())?;
40
41 AbstractionElement::remove(self, deep)?;
42
43 remove_helper(ref_parents, deep)
44 }
45
46 fn new_internal(
47 name: &str,
48 package: &ArPackage,
49 element_type: &ApplicationDataType,
50 size: ApplicationArraySize,
51 ) -> Result<Self, AutosarAbstractionError> {
52 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
53 let application_array_data_type =
54 elements.create_named_sub_element(ElementName::ApplicationArrayDataType, name)?;
55
56 application_array_data_type
57 .create_sub_element(ElementName::Category)?
58 .set_character_data("ARRAY")?;
59
60 let application_array_data_type = Self(application_array_data_type);
61 ApplicationArrayElement::new("Element", &application_array_data_type, element_type)?;
62
63 application_array_data_type.set_size(size)?;
65
66 Ok(application_array_data_type)
67 }
68
69 #[must_use]
71 pub fn array_element(&self) -> Option<ApplicationArrayElement> {
72 self.element().get_sub_element(ElementName::Element)?.try_into().ok()
73 }
74
75 pub fn set_size(&self, size: ApplicationArraySize) -> Result<(), AutosarAbstractionError> {
77 let array_element = self.array_element().ok_or(AutosarAbstractionError::InvalidParameter(
78 "Array data type has no array element".to_string(),
79 ))?;
80 if let Some(datatype) = array_element.data_type() {
81 let is_array_datatype = matches!(datatype, ApplicationDataType::Array(_));
82 if is_array_datatype && matches!(size, ApplicationArraySize::VariableLinear(_)) {
83 return Err(AutosarAbstractionError::InvalidParameter(
84 "When the size type is VariableLinear, the element type may not be an array".to_string(),
85 ));
86 } else if !is_array_datatype
87 && matches!(
88 size,
89 ApplicationArraySize::VariableSquare
90 | ApplicationArraySize::VariableRectangular(_)
91 | ApplicationArraySize::VariableFullyFlexible(_)
92 )
93 {
94 return Err(AutosarAbstractionError::InvalidParameter(
95 "When the size type is VariableSquare, VariableRectangular or VariableFullyFlexible, the element type must be an array".to_string(),
96 ));
97 }
98 }
99 let array_element_elem = array_element.element();
100 match size {
101 ApplicationArraySize::Fixed(size) => {
102 let _ = self
103 .element()
104 .remove_sub_element_kind(ElementName::DynamicArraySizeProfile);
105 array_element_elem
106 .get_or_create_sub_element(ElementName::MaxNumberOfElements)?
107 .set_character_data(size)?;
108 array_element_elem
109 .get_or_create_sub_element(ElementName::ArraySizeSemantics)?
110 .set_character_data(EnumItem::FixedSize)?;
111 let _ = array_element_elem.remove_sub_element_kind(ElementName::ArraySizeHandling);
112 }
113 ApplicationArraySize::VariableLinear(max_size) => {
114 self.element()
115 .get_or_create_sub_element(ElementName::DynamicArraySizeProfile)?
116 .set_character_data("VSA_LINEAR")?;
117 array_element_elem
118 .get_or_create_sub_element(ElementName::MaxNumberOfElements)?
119 .set_character_data(max_size)?;
120 array_element_elem
121 .get_or_create_sub_element(ElementName::ArraySizeSemantics)?
122 .set_character_data(EnumItem::VariableSize)?;
123 array_element_elem
124 .get_or_create_sub_element(ElementName::ArraySizeHandling)?
125 .set_character_data(EnumItem::AllIndicesSameArraySize)?;
126 }
127 ApplicationArraySize::VariableSquare => {
128 self.element()
129 .get_or_create_sub_element(ElementName::DynamicArraySizeProfile)?
130 .set_character_data("VSA_SQUARE")?;
131 let _ = array_element_elem.remove_sub_element_kind(ElementName::MaxNumberOfElements);
132 array_element_elem
133 .get_or_create_sub_element(ElementName::ArraySizeSemantics)?
134 .set_character_data(EnumItem::VariableSize)?;
135 array_element_elem
136 .get_or_create_sub_element(ElementName::ArraySizeHandling)?
137 .set_character_data(EnumItem::InheritedFromArrayElementTypeSize)?;
138 }
139 ApplicationArraySize::VariableRectangular(max_size) => {
140 self.element()
141 .get_or_create_sub_element(ElementName::DynamicArraySizeProfile)?
142 .set_character_data("VSA_RECTANGULAR")?;
143 array_element_elem
144 .get_or_create_sub_element(ElementName::MaxNumberOfElements)?
145 .set_character_data(max_size)?;
146 array_element_elem
147 .get_or_create_sub_element(ElementName::ArraySizeSemantics)?
148 .set_character_data(EnumItem::VariableSize)?;
149 array_element_elem
150 .get_or_create_sub_element(ElementName::ArraySizeHandling)?
151 .set_character_data(EnumItem::AllIndicesSameArraySize)?;
152 }
153 ApplicationArraySize::VariableFullyFlexible(max_size) => {
154 self.element()
155 .get_or_create_sub_element(ElementName::DynamicArraySizeProfile)?
156 .set_character_data("VSA_FULLY_FLEXIBLE")?;
157 array_element_elem
158 .get_or_create_sub_element(ElementName::MaxNumberOfElements)?
159 .set_character_data(max_size)?;
160 array_element_elem
161 .get_or_create_sub_element(ElementName::ArraySizeSemantics)?
162 .set_character_data(EnumItem::VariableSize)?;
163 array_element_elem
164 .get_or_create_sub_element(ElementName::ArraySizeHandling)?
165 .set_character_data(EnumItem::AllIndicesDifferentArraySize)?;
166 }
167 }
168
169 Ok(())
170 }
171
172 #[must_use]
174 pub fn size(&self) -> Option<ApplicationArraySize> {
175 let max_number_of_elements = self
176 .array_element()?
177 .element()
178 .get_sub_element(ElementName::MaxNumberOfElements);
179
180 if let Some(size_profile) = self
181 .element()
182 .get_sub_element(ElementName::DynamicArraySizeProfile)
183 .and_then(|elem| elem.character_data().and_then(|cdata| cdata.string_value()))
184 {
185 match size_profile.as_str() {
186 "VSA_LINEAR" => {
187 let max_size = max_number_of_elements?.character_data()?.parse_integer()?;
188 Some(ApplicationArraySize::VariableLinear(max_size))
189 }
190 "VSA_SQUARE" => Some(ApplicationArraySize::VariableSquare),
191 "VSA_RECTANGULAR" => {
192 let max_size = max_number_of_elements?.character_data()?.parse_integer()?;
193 Some(ApplicationArraySize::VariableRectangular(max_size))
194 }
195 "VSA_FULLY_FLEXIBLE" => {
196 let max_size = max_number_of_elements?.character_data()?.parse_integer()?;
197 Some(ApplicationArraySize::VariableFullyFlexible(max_size))
198 }
199 _ => None,
200 }
201 } else {
202 let size = max_number_of_elements?.character_data()?.parse_integer()?;
203 Some(ApplicationArraySize::Fixed(size))
204 }
205 }
206}
207
208#[derive(Debug, Clone, PartialEq, Eq, Hash)]
212pub enum ApplicationArraySize {
213 Fixed(u64),
215 VariableLinear(u64),
217 VariableSquare,
221 VariableRectangular(u64),
224 VariableFullyFlexible(u64),
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Hash)]
233pub struct ApplicationArrayElement(Element);
234abstraction_element!(ApplicationArrayElement, Element);
235impl IdentifiableAbstractionElement for ApplicationArrayElement {}
236
237impl ApplicationArrayElement {
238 fn new(
239 name: &str,
240 parent: &ApplicationArrayDataType,
241 data_type: &ApplicationDataType,
242 ) -> Result<Self, AutosarAbstractionError> {
243 let application_array_element = parent.element().create_named_sub_element(ElementName::Element, name)?;
244 let application_array_element = Self(application_array_element);
245
246 application_array_element.set_data_type(data_type)?;
247
248 Ok(application_array_element)
249 }
250
251 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
253 let opt_data_type = self.data_type();
254
255 AbstractionElement::remove(self, deep)?;
256
257 if deep
258 && let Some(data_type) = opt_data_type
259 && !is_used(data_type.element())
260 {
261 data_type.remove(deep)?;
262 }
263
264 Ok(())
265 }
266
267 pub fn set_data_type<T: Into<ApplicationDataType> + AbstractionElement>(
269 &self,
270 data_type: &T,
271 ) -> Result<(), AutosarAbstractionError> {
272 let data_type: ApplicationDataType = data_type.clone().into();
273 self.element()
274 .get_or_create_sub_element(ElementName::TypeTref)?
275 .set_reference_target(data_type.element())?;
276 if let Some(category) = data_type.category() {
278 self.element()
279 .get_or_create_sub_element(ElementName::Category)?
280 .set_character_data(category)?;
281 } else {
282 let _ = self.element().remove_sub_element_kind(ElementName::Category);
284 }
285
286 Ok(())
287 }
288
289 #[must_use]
291 pub fn data_type(&self) -> Option<ApplicationDataType> {
292 self.element()
293 .get_sub_element(ElementName::TypeTref)?
294 .get_reference_target()
295 .ok()?
296 .try_into()
297 .ok()
298 }
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, Hash)]
307pub struct ApplicationRecordDataType(Element);
308abstraction_element!(ApplicationRecordDataType, ApplicationRecordDataType);
309impl IdentifiableAbstractionElement for ApplicationRecordDataType {}
310impl AbstractAutosarDataType for ApplicationRecordDataType {}
311
312impl ApplicationRecordDataType {
313 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
315 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
316 let application_record_data_type =
317 elements.create_named_sub_element(ElementName::ApplicationRecordDataType, name)?;
318
319 application_record_data_type
320 .create_sub_element(ElementName::Category)?
321 .set_character_data("STRUCTURE")?;
322
323 Ok(Self(application_record_data_type))
324 }
325
326 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
328 for record_element in self.record_elements() {
329 record_element.remove(deep)?;
330 }
331 let ref_parents = get_reference_parents(self.element())?;
332
333 AbstractionElement::remove(self, deep)?;
334
335 remove_helper(ref_parents, deep)
336 }
337
338 pub fn create_record_element<T: Into<ApplicationDataType> + Clone>(
340 &self,
341 name: &str,
342 data_type: &T,
343 ) -> Result<ApplicationRecordElement, AutosarAbstractionError> {
344 ApplicationRecordElement::new(name, self, &data_type.clone().into())
345 }
346
347 pub fn record_elements(&self) -> impl Iterator<Item = ApplicationRecordElement> + Send + use<> {
349 self.element()
350 .get_sub_element(ElementName::Elements)
351 .into_iter()
352 .flat_map(|elements| elements.sub_elements())
353 .filter_map(|element| ApplicationRecordElement::try_from(element).ok())
354 }
355}
356
357#[derive(Debug, Clone, PartialEq, Eq, Hash)]
361pub struct ApplicationRecordElement(Element);
362abstraction_element!(ApplicationRecordElement, ApplicationRecordElement);
363impl IdentifiableAbstractionElement for ApplicationRecordElement {}
364
365impl ApplicationRecordElement {
366 fn new(
367 name: &str,
368 parent: &ApplicationRecordDataType,
369 data_type: &ApplicationDataType,
370 ) -> Result<Self, AutosarAbstractionError> {
371 let application_record_element = parent
372 .element()
373 .get_or_create_sub_element(ElementName::Elements)?
374 .create_named_sub_element(ElementName::ApplicationRecordElement, name)?;
375
376 let application_record_element = Self(application_record_element);
377 application_record_element.set_data_type(data_type)?;
378
379 Ok(application_record_element)
380 }
381
382 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
384 let opt_data_type = self.data_type();
385
386 AbstractionElement::remove(self, deep)?;
387
388 if deep
389 && let Some(data_type) = opt_data_type
390 && !is_used(data_type.element())
391 {
392 data_type.remove(deep)?;
393 }
394
395 Ok(())
396 }
397
398 pub fn set_data_type<T: Into<ApplicationDataType> + AbstractionElement>(
400 &self,
401 data_type: &T,
402 ) -> Result<(), AutosarAbstractionError> {
403 let data_type: ApplicationDataType = data_type.clone().into();
404 self.element()
405 .get_or_create_sub_element(ElementName::TypeTref)?
406 .set_reference_target(data_type.element())?;
407 if let Some(category) = data_type.category() {
408 self.element()
409 .get_or_create_sub_element(ElementName::Category)?
410 .set_character_data(category)?;
411 } else {
412 let _ = self.element().remove_sub_element_kind(ElementName::Category);
414 }
415
416 Ok(())
417 }
418
419 #[must_use]
421 pub fn data_type(&self) -> Option<ApplicationDataType> {
422 self.element()
423 .get_sub_element(ElementName::TypeTref)?
424 .get_reference_target()
425 .ok()?
426 .try_into()
427 .ok()
428 }
429}
430
431#[derive(Debug, Clone, PartialEq, Eq, Hash)]
437pub struct ApplicationPrimitiveDataType(Element);
438abstraction_element!(ApplicationPrimitiveDataType, ApplicationPrimitiveDataType);
439impl IdentifiableAbstractionElement for ApplicationPrimitiveDataType {}
440impl AbstractAutosarDataType for ApplicationPrimitiveDataType {}
441
442impl ApplicationPrimitiveDataType {
443 pub(crate) fn new(
445 name: &str,
446 package: &ArPackage,
447 category: ApplicationPrimitiveCategory,
448 compu_method: Option<&CompuMethod>,
449 unit: Option<&Unit>,
450 data_constraint: Option<&DataConstr>,
451 ) -> Result<Self, AutosarAbstractionError> {
452 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
453 let application_primitive_data_type =
454 elements.create_named_sub_element(ElementName::ApplicationPrimitiveDataType, name)?;
455
456 let application_primitive_data_type = Self(application_primitive_data_type);
457
458 application_primitive_data_type.set_category(category)?;
459 application_primitive_data_type.set_compu_method(compu_method)?;
460 application_primitive_data_type.set_unit(unit)?;
461 application_primitive_data_type.set_data_constraint(data_constraint)?;
462
463 Ok(application_primitive_data_type)
464 }
465
466 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
468 let opt_compu_method = self.compu_method();
469 let opt_unit = self.unit();
470 let opt_data_constraint = self.data_constraint();
471 let ref_parents = get_reference_parents(self.element())?;
472
473 AbstractionElement::remove(self, deep)?;
474
475 if deep {
476 if let Some(compu_method) = opt_compu_method
477 && !is_used(compu_method.element())
478 {
479 compu_method.remove(deep)?;
480 }
481 if let Some(unit) = opt_unit
482 && !is_used(unit.element())
483 {
484 unit.remove(deep)?;
485 }
486 if let Some(data_constraint) = opt_data_constraint
487 && !is_used(data_constraint.element())
488 {
489 data_constraint.remove(deep)?;
490 }
491 }
492
493 remove_helper(ref_parents, deep)
494 }
495
496 pub fn set_category(&self, category: ApplicationPrimitiveCategory) -> Result<(), AutosarAbstractionError> {
498 self.element()
499 .get_or_create_sub_element(ElementName::Category)?
500 .set_character_data(category.to_string())?;
501
502 Ok(())
503 }
504
505 #[must_use]
507 pub fn category(&self) -> Option<ApplicationPrimitiveCategory> {
508 self.element()
509 .get_sub_element(ElementName::Category)?
510 .character_data()?
511 .string_value()?
512 .parse()
513 .ok()
514 }
515
516 pub fn set_compu_method(&self, compu_method: Option<&CompuMethod>) -> Result<(), AutosarAbstractionError> {
518 if let Some(compu_method) = compu_method {
519 self.element()
520 .get_or_create_sub_element(ElementName::SwDataDefProps)?
521 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
522 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
523 .get_or_create_sub_element(ElementName::CompuMethodRef)?
524 .set_reference_target(compu_method.element())?;
525 } else {
526 let _ = self
527 .element()
528 .get_sub_element(ElementName::SwDataDefProps)
529 .and_then(|sddp| sddp.get_sub_element(ElementName::SwDataDefPropsVariants))
530 .and_then(|sddpv| sddpv.get_sub_element(ElementName::SwDataDefPropsConditional))
531 .and_then(|sddpc| sddpc.remove_sub_element_kind(ElementName::CompuMethodRef).ok());
532 }
533
534 Ok(())
535 }
536
537 #[must_use]
539 pub fn compu_method(&self) -> Option<CompuMethod> {
540 self.element()
541 .get_sub_element(ElementName::SwDataDefProps)?
542 .get_sub_element(ElementName::SwDataDefPropsVariants)?
543 .get_sub_element(ElementName::SwDataDefPropsConditional)?
544 .get_sub_element(ElementName::CompuMethodRef)?
545 .get_reference_target()
546 .ok()?
547 .try_into()
548 .ok()
549 }
550
551 pub fn set_unit(&self, unit: Option<&Unit>) -> Result<(), AutosarAbstractionError> {
553 if let Some(unit) = unit {
554 self.element()
555 .get_or_create_sub_element(ElementName::SwDataDefProps)?
556 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
557 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
558 .get_or_create_sub_element(ElementName::UnitRef)?
559 .set_reference_target(unit.element())?;
560 } else {
561 let _ = self
562 .element()
563 .get_sub_element(ElementName::SwDataDefProps)
564 .and_then(|sddp| sddp.get_sub_element(ElementName::SwDataDefPropsVariants))
565 .and_then(|sddpv| sddpv.get_sub_element(ElementName::SwDataDefPropsConditional))
566 .and_then(|sddpc| sddpc.remove_sub_element_kind(ElementName::UnitRef).ok());
567 }
568
569 Ok(())
570 }
571
572 #[must_use]
574 pub fn unit(&self) -> Option<Unit> {
575 self.element()
576 .get_sub_element(ElementName::SwDataDefProps)?
577 .get_sub_element(ElementName::SwDataDefPropsVariants)?
578 .get_sub_element(ElementName::SwDataDefPropsConditional)?
579 .get_sub_element(ElementName::UnitRef)?
580 .get_reference_target()
581 .ok()?
582 .try_into()
583 .ok()
584 }
585
586 pub fn set_data_constraint(&self, data_constraint: Option<&DataConstr>) -> Result<(), AutosarAbstractionError> {
588 if let Some(data_constraint) = data_constraint {
589 self.element()
590 .get_or_create_sub_element(ElementName::SwDataDefProps)?
591 .get_or_create_sub_element(ElementName::SwDataDefPropsVariants)?
592 .get_or_create_sub_element(ElementName::SwDataDefPropsConditional)?
593 .get_or_create_sub_element(ElementName::DataConstrRef)?
594 .set_reference_target(data_constraint.element())?;
595 } else {
596 let _ = self
597 .element()
598 .get_sub_element(ElementName::SwDataDefProps)
599 .and_then(|sddp| sddp.get_sub_element(ElementName::SwDataDefPropsVariants))
600 .and_then(|sddpv| sddpv.get_sub_element(ElementName::SwDataDefPropsConditional))
601 .and_then(|sddpc| sddpc.remove_sub_element_kind(ElementName::DataConstrRef).ok());
602 }
603
604 Ok(())
605 }
606
607 #[must_use]
609 pub fn data_constraint(&self) -> Option<DataConstr> {
610 self.element()
611 .get_sub_element(ElementName::SwDataDefProps)?
612 .get_sub_element(ElementName::SwDataDefPropsVariants)?
613 .get_sub_element(ElementName::SwDataDefPropsConditional)?
614 .get_sub_element(ElementName::DataConstrRef)?
615 .get_reference_target()
616 .ok()?
617 .try_into()
618 .ok()
619 }
620}
621
622#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
626pub enum ApplicationPrimitiveCategory {
627 Value,
629 ValBlk,
631 String,
633 Boolean,
635 ComAxis,
637 ResAxis,
639 Curve,
641 Map,
643 Cuboid,
645 Cube4,
647 Cube5,
649}
650
651impl std::fmt::Display for ApplicationPrimitiveCategory {
652 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
653 match self {
654 ApplicationPrimitiveCategory::Value => f.write_str("VALUE"),
655 ApplicationPrimitiveCategory::ValBlk => f.write_str("VAL_BLK"),
656 ApplicationPrimitiveCategory::String => f.write_str("STRING"),
657 ApplicationPrimitiveCategory::Boolean => f.write_str("BOOLEAN"),
658 ApplicationPrimitiveCategory::ComAxis => f.write_str("COM_AXIS"),
659 ApplicationPrimitiveCategory::ResAxis => f.write_str("RES_AXIS"),
660 ApplicationPrimitiveCategory::Curve => f.write_str("CURVE"),
661 ApplicationPrimitiveCategory::Map => f.write_str("MAP"),
662 ApplicationPrimitiveCategory::Cuboid => f.write_str("CUBOID"),
663 ApplicationPrimitiveCategory::Cube4 => f.write_str("CUBE_4"),
664 ApplicationPrimitiveCategory::Cube5 => f.write_str("CUBE_5"),
665 }
666 }
667}
668
669impl std::str::FromStr for ApplicationPrimitiveCategory {
670 type Err = AutosarAbstractionError;
671
672 fn from_str(s: &str) -> Result<Self, Self::Err> {
673 match s {
674 "VALUE" => Ok(ApplicationPrimitiveCategory::Value),
675 "VAL_BLK" => Ok(ApplicationPrimitiveCategory::ValBlk),
676 "STRING" => Ok(ApplicationPrimitiveCategory::String),
677 "BOOLEAN" => Ok(ApplicationPrimitiveCategory::Boolean),
678 "COM_AXIS" => Ok(ApplicationPrimitiveCategory::ComAxis),
679 "RES_AXIS" => Ok(ApplicationPrimitiveCategory::ResAxis),
680 "CURVE" => Ok(ApplicationPrimitiveCategory::Curve),
681 "MAP" => Ok(ApplicationPrimitiveCategory::Map),
682 "CUBOID" => Ok(ApplicationPrimitiveCategory::Cuboid),
683 "CUBE_4" => Ok(ApplicationPrimitiveCategory::Cube4),
684 "CUBE_5" => Ok(ApplicationPrimitiveCategory::Cube5),
685 _ => Err(AutosarAbstractionError::ValueConversionError {
686 value: s.to_string(),
687 dest: "ApplicationPrimitiveCategory".to_string(),
688 }),
689 }
690 }
691}
692
693#[derive(Debug, Clone, PartialEq, Eq, Hash)]
697pub enum ApplicationDataType {
698 Array(ApplicationArrayDataType),
700 Record(ApplicationRecordDataType),
702 Primitive(ApplicationPrimitiveDataType),
704}
705
706impl AbstractionElement for ApplicationDataType {
707 fn element(&self) -> &Element {
708 match self {
709 ApplicationDataType::Array(e) => e.element(),
710 ApplicationDataType::Record(e) => e.element(),
711 ApplicationDataType::Primitive(e) => e.element(),
712 }
713 }
714}
715
716impl TryFrom<Element> for ApplicationDataType {
717 type Error = AutosarAbstractionError;
718
719 fn try_from(element: Element) -> Result<Self, Self::Error> {
720 match element.element_name() {
721 ElementName::ApplicationArrayDataType => Ok(ApplicationDataType::Array(element.try_into()?)),
722 ElementName::ApplicationRecordDataType => Ok(ApplicationDataType::Record(element.try_into()?)),
723 ElementName::ApplicationPrimitiveDataType => Ok(ApplicationDataType::Primitive(element.try_into()?)),
724 _ => Err(AutosarAbstractionError::ConversionError {
725 element,
726 dest: "ApplicationDataType".to_string(),
727 }),
728 }
729 }
730}
731
732impl IdentifiableAbstractionElement for ApplicationDataType {}
733
734impl From<ApplicationPrimitiveDataType> for ApplicationDataType {
735 fn from(val: ApplicationPrimitiveDataType) -> Self {
736 ApplicationDataType::Primitive(val)
737 }
738}
739
740impl From<ApplicationRecordDataType> for ApplicationDataType {
741 fn from(val: ApplicationRecordDataType) -> Self {
742 ApplicationDataType::Record(val)
743 }
744}
745
746impl From<ApplicationArrayDataType> for ApplicationDataType {
747 fn from(val: ApplicationArrayDataType) -> Self {
748 ApplicationDataType::Array(val)
749 }
750}
751
752impl ApplicationDataType {
753 #[must_use]
755 pub fn category(&self) -> Option<String> {
756 self.element()
757 .get_sub_element(ElementName::Category)?
758 .character_data()?
759 .string_value()
760 }
761
762 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
764 match self {
765 ApplicationDataType::Array(e) => e.remove(deep),
766 ApplicationDataType::Record(e) => e.remove(deep),
767 ApplicationDataType::Primitive(e) => e.remove(deep),
768 }
769 }
770}
771
772fn remove_helper(ref_parents: Vec<(Element, Element)>, deep: bool) -> Result<(), AutosarAbstractionError> {
775 for (named_parent, parent) in ref_parents {
776 match named_parent.element_name() {
777 ElementName::Element => {
778 if let Ok(app_data_type_ref) = ApplicationArrayElement::try_from(named_parent) {
779 app_data_type_ref.remove(deep)?;
780 }
781 }
782 ElementName::ApplicationRecordElement => {
783 if let Ok(app_data_type_ref) = ApplicationRecordElement::try_from(named_parent) {
784 app_data_type_ref.remove(deep)?;
785 }
786 }
787 ElementName::DataTypeMappingSet => {
788 if let Ok(data_type_map) = DataTypeMap::try_from(parent) {
790 data_type_map.remove(deep)?;
791 }
792 }
793 ElementName::ParameterDataPrototype => {
794 if let Ok(param_prototype) = ParameterDataPrototype::try_from(named_parent) {
795 param_prototype.remove(deep)?;
796 }
797 }
798 ElementName::VariableDataPrototype => {
799 if let Ok(var_data_prototype) = VariableDataPrototype::try_from(parent) {
800 var_data_prototype.remove(deep)?;
801 }
802 }
803 ElementName::ArgumentDataPrototype => {
804 if let Ok(arg_data_prototype) = ArgumentDataPrototype::try_from(parent) {
805 arg_data_prototype.remove(deep)?;
806 }
807 }
808 _ => {}
809 }
810 }
811
812 Ok(())
813}
814
815#[cfg(test)]
818mod tests {
819 use super::*;
820 use crate::{
821 AutosarModelAbstraction,
822 datatype::{BaseTypeEncoding, ImplementationDataTypeSettings},
823 software_component::ArgumentDirection,
824 };
825 use autosar_data::AutosarVersion;
826 use datatype::{CompuMethodContent, CompuMethodLinearContent};
827
828 #[test]
829 fn test_application_array_data_type() {
830 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
831 let package = model.get_or_create_package("/DataTypes").unwrap();
832 let element_type = ApplicationPrimitiveDataType::new(
833 "Element",
834 &package,
835 ApplicationPrimitiveCategory::Value,
836 None,
837 None,
838 None,
839 )
840 .unwrap();
841 let array_data_type =
842 ApplicationArrayDataType::new("Array", &package, &element_type, ApplicationArraySize::Fixed(10)).unwrap();
843 let array_type_2 =
844 ApplicationArrayDataType::new("Array2", &package, &element_type, ApplicationArraySize::Fixed(100)).unwrap();
845
846 assert_eq!(
847 array_data_type.array_element().unwrap().data_type().unwrap(),
848 ApplicationDataType::Primitive(element_type)
849 );
850 assert_eq!(array_data_type.size().unwrap(), ApplicationArraySize::Fixed(10));
851
852 array_data_type
853 .set_size(ApplicationArraySize::VariableLinear(100))
854 .unwrap();
855 assert_eq!(
856 array_data_type.size().unwrap(),
857 ApplicationArraySize::VariableLinear(100)
858 );
859
860 let result = array_data_type.set_size(ApplicationArraySize::VariableSquare);
862 assert!(result.is_err());
863 let result = array_data_type.set_size(ApplicationArraySize::VariableRectangular(100));
864 assert!(result.is_err());
865 let result = array_data_type.set_size(ApplicationArraySize::VariableFullyFlexible(100));
866 assert!(result.is_err());
867
868 array_data_type
870 .array_element()
871 .unwrap()
872 .set_data_type(&array_type_2)
873 .unwrap();
874 array_data_type.set_size(ApplicationArraySize::VariableSquare).unwrap();
875 assert_eq!(array_data_type.size().unwrap(), ApplicationArraySize::VariableSquare);
876 array_data_type
877 .set_size(ApplicationArraySize::VariableRectangular(100))
878 .unwrap();
879 assert_eq!(
880 array_data_type.size().unwrap(),
881 ApplicationArraySize::VariableRectangular(100)
882 );
883 array_data_type
884 .set_size(ApplicationArraySize::VariableFullyFlexible(100))
885 .unwrap();
886 assert_eq!(
887 array_data_type.size().unwrap(),
888 ApplicationArraySize::VariableFullyFlexible(100)
889 );
890
891 let element_type_2 = ApplicationPrimitiveDataType::new(
893 "Element2",
894 &package,
895 ApplicationPrimitiveCategory::Value,
896 None,
897 None,
898 None,
899 )
900 .unwrap();
901 let array_element = array_data_type.array_element().unwrap();
902 array_element.set_data_type(&element_type_2).unwrap();
903 assert_eq!(
904 array_element.data_type().unwrap(),
905 ApplicationDataType::Primitive(element_type_2)
906 );
907 }
908
909 #[test]
910 fn test_application_record_data_type() {
911 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
912 let package = model.get_or_create_package("/DataTypes").unwrap();
913 let record_data_type = ApplicationRecordDataType::new("Record", &package).unwrap();
914 let element_type = ApplicationPrimitiveDataType::new(
915 "Element",
916 &package,
917 ApplicationPrimitiveCategory::Value,
918 None,
919 None,
920 None,
921 )
922 .unwrap();
923 let record_element = record_data_type
924 .create_record_element("Element", &element_type)
925 .unwrap();
926
927 assert_eq!(
928 record_element.data_type().unwrap(),
929 ApplicationDataType::Primitive(element_type)
930 );
931 assert_eq!(record_data_type.record_elements().next().unwrap(), record_element);
932 }
933
934 #[test]
935 fn test_application_primitive_data_type() {
936 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
937 let package = model.get_or_create_package("/DataTypes").unwrap();
938 let compu_method = CompuMethod::new(
939 "CompuMethod",
940 &package,
941 CompuMethodContent::Linear(CompuMethodLinearContent {
942 direction: datatype::CompuScaleDirection::IntToPhys,
943 offset: 0.0,
944 factor: 100.0,
945 divisor: 1.0,
946 lower_limit: None,
947 upper_limit: None,
948 }),
949 )
950 .unwrap();
951 let unit = Unit::new("Unit", &package, Some("Unit name")).unwrap();
952 let data_constraint = DataConstr::new("DataConstraint", &package).unwrap();
953 let primitive_data_type = ApplicationPrimitiveDataType::new(
954 "Primitive",
955 &package,
956 ApplicationPrimitiveCategory::Value,
957 Some(&compu_method),
958 Some(&unit),
959 Some(&data_constraint),
960 )
961 .unwrap();
962
963 assert_eq!(
964 primitive_data_type.category().unwrap(),
965 ApplicationPrimitiveCategory::Value
966 );
967 assert_eq!(primitive_data_type.compu_method().unwrap(), compu_method);
968 assert_eq!(primitive_data_type.unit().unwrap(), unit);
969 assert_eq!(primitive_data_type.data_constraint().unwrap(), data_constraint);
970
971 primitive_data_type
972 .set_category(ApplicationPrimitiveCategory::Boolean)
973 .unwrap();
974 assert_eq!(
975 primitive_data_type.category().unwrap(),
976 ApplicationPrimitiveCategory::Boolean
977 );
978 primitive_data_type.set_compu_method(None).unwrap();
979 assert!(primitive_data_type.compu_method().is_none());
980 primitive_data_type.set_unit(None).unwrap();
981 assert!(primitive_data_type.unit().is_none());
982 primitive_data_type.set_data_constraint(None).unwrap();
983 assert!(primitive_data_type.data_constraint().is_none());
984 }
985
986 #[test]
987 fn test_application_data_type() {
988 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
989 let package = model.get_or_create_package("/DataTypes").unwrap();
990 let element_type = ApplicationPrimitiveDataType::new(
991 "Element",
992 &package,
993 ApplicationPrimitiveCategory::Value,
994 None,
995 None,
996 None,
997 )
998 .unwrap();
999 let array_data_type =
1000 ApplicationArrayDataType::new("Array", &package, &element_type, ApplicationArraySize::Fixed(10)).unwrap();
1001 let record_data_type = ApplicationRecordDataType::new("Record", &package).unwrap();
1002 let primitive_data_type = ApplicationPrimitiveDataType::new(
1003 "Primitive",
1004 &package,
1005 ApplicationPrimitiveCategory::Value,
1006 None,
1007 None,
1008 None,
1009 )
1010 .unwrap();
1011
1012 let data_type: ApplicationDataType = array_data_type.clone().into();
1013 assert_eq!(data_type, ApplicationDataType::Array(array_data_type.clone()));
1014 assert_eq!(data_type.category().unwrap(), "ARRAY");
1015
1016 let data_type: ApplicationDataType = record_data_type.clone().into();
1017 assert_eq!(data_type, ApplicationDataType::Record(record_data_type.clone()));
1018 assert_eq!(data_type.category().unwrap(), "STRUCTURE");
1019
1020 let data_type: ApplicationDataType = primitive_data_type.clone().into();
1021 assert_eq!(data_type, ApplicationDataType::Primitive(primitive_data_type.clone()));
1022 assert_eq!(data_type.category().unwrap(), "VALUE");
1023
1024 let result = ApplicationDataType::try_from(package.element().clone());
1025 assert!(result.is_err());
1026 }
1027
1028 #[test]
1029 fn remove() {
1030 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1031 let package = model.get_or_create_package("/DataTypes").unwrap();
1032 let element_type = package
1033 .create_application_primitive_data_type(
1034 "AppPrimitive",
1035 ApplicationPrimitiveCategory::Value,
1036 None,
1037 None,
1038 None,
1039 )
1040 .unwrap();
1041 let array_data_type = package
1042 .create_application_array_data_type("AppArray", &element_type, ApplicationArraySize::Fixed(10))
1043 .unwrap();
1044
1045 let base_type = package
1047 .create_sw_base_type("uint8", 8, BaseTypeEncoding::TwosComplement, None, None, Some("uint8"))
1048 .unwrap();
1049 let impl_array = package
1050 .create_implementation_data_type(&ImplementationDataTypeSettings::Array {
1051 name: "ImplArray".to_string(),
1052 length: 10,
1053 element_type: Box::new(ImplementationDataTypeSettings::Value {
1054 name: "ImplPrimitive".to_string(),
1055 base_type,
1056 compu_method: None,
1057 data_constraint: None,
1058 }),
1059 })
1060 .unwrap();
1061
1062 let data_type_mapping_set = package.create_data_type_mapping_set("DataTypeMappingSet").unwrap();
1064 data_type_mapping_set
1065 .create_data_type_map(&impl_array, &array_data_type)
1066 .unwrap();
1067
1068 let sr_interface = package.create_sender_receiver_interface("SRInterface").unwrap();
1070 let _vdp = sr_interface.create_data_element("VDP", &array_data_type).unwrap();
1071 let cs_interface = package.create_client_server_interface("CSInterface").unwrap();
1073 let cso = cs_interface.create_operation("ADP").unwrap();
1074 let _adp = cso
1075 .create_argument("ADP", &array_data_type, ArgumentDirection::In)
1076 .unwrap();
1077
1078 let record_data_type = package.create_application_record_data_type("AppRecord").unwrap();
1080 let _record_element = record_data_type
1081 .create_record_element("RecordElement", &array_data_type)
1082 .unwrap();
1083
1084 array_data_type.remove(true).unwrap();
1086
1087 assert_eq!(data_type_mapping_set.data_type_maps().count(), 0);
1089 assert_eq!(sr_interface.data_elements().count(), 0);
1090 assert_eq!(cso.arguments().count(), 0);
1091 assert_eq!(record_data_type.record_elements().count(), 0);
1092 }
1093}