1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, Element, EnumItem, IdentifiableAbstractionElement,
3 abstraction_element, datatype,
4};
5use autosar_data::ElementName;
6use datatype::{AbstractAutosarDataType, CompuMethod, DataConstr, SwBaseType};
7use std::fmt::Display;
8
9pub trait AbstractImplementationDataType: IdentifiableAbstractionElement {
11 fn category(&self) -> Option<ImplementationDataCategory> {
13 self.element()
14 .get_sub_element(ElementName::Category)?
15 .character_data()?
16 .string_value()?
17 .as_str()
18 .try_into()
19 .ok()
20 }
21
22 fn sub_elements(&self) -> impl Iterator<Item = ImplementationDataTypeElement> + Send + 'static {
24 self.element()
25 .get_sub_element(ElementName::SubElements)
26 .into_iter()
27 .flat_map(|elem| elem.sub_elements())
28 .filter_map(|elem| ImplementationDataTypeElement::try_from(elem).ok())
29 }
30
31 fn base_type(&self) -> Option<SwBaseType> {
33 let category = self.category()?;
34 if category != ImplementationDataCategory::Value {
35 return None;
36 }
37 self.element()
38 .get_sub_element(ElementName::SwDataDefProps)?
39 .get_sub_element(ElementName::SwDataDefPropsVariants)?
40 .get_sub_element(ElementName::SwDataDefPropsConditional)?
41 .get_sub_element(ElementName::BaseTypeRef)?
42 .get_reference_target()
43 .ok()?
44 .try_into()
45 .ok()
46 }
47
48 fn compu_method(&self) -> Option<CompuMethod> {
50 let category = self.category()?;
51 if category != ImplementationDataCategory::Value && category != ImplementationDataCategory::TypeReference {
52 return None;
53 }
54 self.element()
55 .get_sub_element(ElementName::SwDataDefProps)?
56 .get_sub_element(ElementName::SwDataDefPropsVariants)?
57 .get_sub_element(ElementName::SwDataDefPropsConditional)?
58 .get_sub_element(ElementName::CompuMethodRef)
59 .and_then(|cmref| cmref.get_reference_target().ok())
60 .and_then(|refelem| refelem.try_into().ok())
61 }
62
63 fn data_constraint(&self) -> Option<DataConstr> {
65 let category = self.category()?;
66 if category != ImplementationDataCategory::Value && category != ImplementationDataCategory::TypeReference {
67 return None;
68 }
69 self.element()
70 .get_sub_element(ElementName::SwDataDefProps)?
71 .get_sub_element(ElementName::SwDataDefPropsVariants)?
72 .get_sub_element(ElementName::SwDataDefPropsConditional)?
73 .get_sub_element(ElementName::DataConstrRef)
74 .and_then(|dcref| dcref.get_reference_target().ok())
75 .and_then(|refelem| refelem.try_into().ok())
76 }
77
78 fn referenced_type(&self) -> Option<ImplementationDataType> {
80 let category = self.category()?;
81 if category != ImplementationDataCategory::TypeReference {
82 return None;
83 }
84 self.element()
85 .get_sub_element(ElementName::SwDataDefProps)?
86 .get_sub_element(ElementName::SwDataDefPropsVariants)?
87 .get_sub_element(ElementName::SwDataDefPropsConditional)?
88 .get_sub_element(ElementName::ImplementationDataTypeRef)?
89 .get_reference_target()
90 .ok()?
91 .try_into()
92 .ok()
93 }
94
95 fn array_size(&self) -> Option<u32> {
97 let category = self.category()?;
98 if category != ImplementationDataCategory::Array {
99 return None;
100 }
101 self.sub_elements()
102 .next()?
103 .element()
104 .get_sub_element(ElementName::ArraySize)?
105 .character_data()?
106 .parse_integer()
107 }
108
109 fn data_pointer_target(&self) -> Option<DataPointerTarget> {
111 let category = self.category()?;
112 if category != ImplementationDataCategory::DataReference {
113 return None;
114 }
115 let sw_pointer_target_props = self
116 .element()
117 .get_sub_element(ElementName::SwDataDefProps)?
118 .get_sub_element(ElementName::SwDataDefPropsVariants)?
119 .get_sub_element(ElementName::SwDataDefPropsConditional)?
120 .get_sub_element(ElementName::SwPointerTargetProps)?
121 .get_sub_element(ElementName::SwDataDefProps)?
122 .get_sub_element(ElementName::SwDataDefPropsVariants)?
123 .get_sub_element(ElementName::SwDataDefPropsConditional)?;
124 if let Some(base_type) = sw_pointer_target_props
125 .get_sub_element(ElementName::BaseTypeRef)
126 .and_then(|elem| elem.get_reference_target().ok())
127 {
128 Some(DataPointerTarget::BaseType(base_type.try_into().ok()?))
129 } else if let Some(impl_data_type) = sw_pointer_target_props
130 .get_sub_element(ElementName::ImplementationDataTypeRef)
131 .and_then(|elem| elem.get_reference_target().ok())
132 {
133 Some(DataPointerTarget::ImplementationDataType(
134 impl_data_type.try_into().ok()?,
135 ))
136 } else {
137 None
138 }
139 }
140
141 fn apply_settings(&self, settings: &ImplementationDataTypeSettings) -> Result<(), AutosarAbstractionError> {
146 self.set_name(settings.name())?;
147 apply_impl_data_settings(self.element(), settings)
148 }
149
150 fn settings(&self) -> Option<ImplementationDataTypeSettings> {
152 let category = self.category()?;
153 match category {
154 ImplementationDataCategory::Value => Some(ImplementationDataTypeSettings::Value {
155 name: self.name()?,
156 base_type: self.base_type()?,
157 compu_method: self.compu_method(),
158 data_constraint: self.data_constraint(),
159 }),
160 ImplementationDataCategory::Array => {
161 let element_settings = self.sub_elements().next()?.settings()?;
162 Some(ImplementationDataTypeSettings::Array {
163 name: self.name()?,
164 length: self.array_size()?,
165 element_type: Box::new(element_settings),
166 })
167 }
168 ImplementationDataCategory::Structure => {
169 let elements = self
170 .sub_elements()
171 .map(|elem| elem.settings())
172 .collect::<Option<Vec<_>>>()?;
173 Some(ImplementationDataTypeSettings::Structure {
174 name: self.name()?,
175 elements,
176 })
177 }
178 ImplementationDataCategory::Union => {
179 let elements = self
180 .sub_elements()
181 .map(|elem| elem.settings())
182 .collect::<Option<Vec<_>>>()?;
183 Some(ImplementationDataTypeSettings::Union {
184 name: self.name()?,
185 elements,
186 })
187 }
188 ImplementationDataCategory::DataReference => {
189 let sw_pointer_target_props = self
190 .element()
191 .get_sub_element(ElementName::SwDataDefProps)?
192 .get_sub_element(ElementName::SwDataDefPropsVariants)?
193 .get_sub_element(ElementName::SwDataDefPropsConditional)?
194 .get_sub_element(ElementName::SwPointerTargetProps)?
195 .get_sub_element(ElementName::SwDataDefProps)?
196 .get_sub_element(ElementName::SwDataDefPropsVariants)?
197 .get_sub_element(ElementName::SwDataDefPropsConditional)?;
198 let target = if let Some(base_type) = sw_pointer_target_props
199 .get_sub_element(ElementName::BaseTypeRef)
200 .and_then(|elem| elem.get_reference_target().ok())
201 {
202 DataPointerTarget::BaseType(base_type.try_into().ok()?)
203 } else if let Some(impl_data_type) = sw_pointer_target_props
204 .get_sub_element(ElementName::ImplementationDataTypeRef)
205 .and_then(|elem| elem.get_reference_target().ok())
206 {
207 DataPointerTarget::ImplementationDataType(impl_data_type.try_into().ok()?)
208 } else {
209 return None;
210 };
211 Some(ImplementationDataTypeSettings::DataReference {
212 name: self.name()?,
213 target,
214 })
215 }
216 ImplementationDataCategory::FunctionReference => {
217 Some(ImplementationDataTypeSettings::FunctionReference { name: self.name()? })
218 }
219 ImplementationDataCategory::TypeReference => Some(ImplementationDataTypeSettings::TypeReference {
220 name: self.name()?,
221 reftype: self.referenced_type()?,
222 compu_method: self.compu_method(),
223 data_constraint: self.data_constraint(),
224 }),
225 }
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Hash)]
235pub struct ImplementationDataType(Element);
236abstraction_element!(ImplementationDataType, ImplementationDataType);
237impl IdentifiableAbstractionElement for ImplementationDataType {}
238impl AbstractAutosarDataType for ImplementationDataType {}
239impl AbstractImplementationDataType for ImplementationDataType {}
240
241impl ImplementationDataType {
242 pub(crate) fn new(
244 package: &ArPackage,
245 settings: &ImplementationDataTypeSettings,
246 ) -> Result<Self, AutosarAbstractionError> {
247 let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
248 let implementation_data_type =
249 elements.create_named_sub_element(ElementName::ImplementationDataType, settings.name())?;
250 let implementation_data_type = Self(implementation_data_type);
251 implementation_data_type.apply_settings(settings)?;
252
253 Ok(implementation_data_type)
254 }
255}
256
257#[derive(Debug, Clone, PartialEq, Eq, Hash)]
261pub struct ImplementationDataTypeElement(Element);
262abstraction_element!(ImplementationDataTypeElement, ImplementationDataTypeElement);
263impl IdentifiableAbstractionElement for ImplementationDataTypeElement {}
264impl AbstractImplementationDataType for ImplementationDataTypeElement {}
265
266impl ImplementationDataTypeElement {
267 pub(crate) fn new(
268 parent: &Element,
269 settings: &ImplementationDataTypeSettings,
270 ) -> Result<Self, AutosarAbstractionError> {
271 let implementation_data_type_element =
272 parent.create_named_sub_element(ElementName::ImplementationDataTypeElement, settings.name())?;
273 let implementation_data_type_element = Self(implementation_data_type_element);
274 implementation_data_type_element.apply_settings(settings)?;
275
276 Ok(implementation_data_type_element)
277 }
278}
279
280fn apply_impl_data_settings(
283 element: &Element,
284 settings: &ImplementationDataTypeSettings,
285) -> Result<(), AutosarAbstractionError> {
286 let _ = element.remove_sub_element_kind(ElementName::Category);
288 let _ = element.remove_sub_element_kind(ElementName::SubElements);
289 let _ = element.remove_sub_element_kind(ElementName::SwDataDefProps);
290 let _ = element.remove_sub_element_kind(ElementName::DynamicArraySizeProfile);
292
293 match settings {
294 ImplementationDataTypeSettings::Value {
295 base_type,
296 compu_method,
297 data_constraint,
298 ..
299 } => {
300 element
301 .create_sub_element(ElementName::Category)?
302 .set_character_data("VALUE")?;
303 let sw_data_def_props = element
304 .create_sub_element(ElementName::SwDataDefProps)?
305 .create_sub_element(ElementName::SwDataDefPropsVariants)?
306 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
307 sw_data_def_props
308 .create_sub_element(ElementName::BaseTypeRef)?
309 .set_reference_target(base_type.element())?;
310 if let Some(compu_method) = compu_method {
311 sw_data_def_props
312 .create_sub_element(ElementName::CompuMethodRef)?
313 .set_reference_target(compu_method.element())?;
314 }
315 if let Some(data_constraint) = data_constraint {
316 sw_data_def_props
317 .create_sub_element(ElementName::DataConstrRef)?
318 .set_reference_target(data_constraint.element())?;
319 }
320 }
321 ImplementationDataTypeSettings::Array {
322 length, element_type, ..
323 } => {
324 element
325 .create_sub_element(ElementName::Category)?
326 .set_character_data("ARRAY")?;
327 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
328 let array_element = ImplementationDataTypeElement::new(&sub_elements, element_type)?;
329 array_element
330 .element()
331 .create_sub_element(ElementName::ArraySize)?
332 .set_character_data(u64::from(*length))?;
333 array_element
334 .element()
335 .create_sub_element(ElementName::ArraySizeSemantics)?
336 .set_character_data(EnumItem::FixedSize)?;
337 }
338 ImplementationDataTypeSettings::Structure { elements, .. } => {
339 element
340 .create_sub_element(ElementName::Category)?
341 .set_character_data("STRUCTURE")?;
342 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
343 for sub_element in elements {
344 ImplementationDataTypeElement::new(&sub_elements, sub_element)?;
345 }
346 }
347 ImplementationDataTypeSettings::Union { elements, .. } => {
348 element
349 .create_sub_element(ElementName::Category)?
350 .set_character_data("UNION")?;
351 let sub_elements = element.get_or_create_sub_element(ElementName::SubElements)?;
352 for sub_element in elements {
353 ImplementationDataTypeElement::new(&sub_elements, sub_element)?;
354 }
355 }
356 ImplementationDataTypeSettings::DataReference { target, .. } => {
357 element
358 .create_sub_element(ElementName::Category)?
359 .set_character_data("DATA_REFERENCE")?;
360 let pointer_props = element
361 .create_sub_element(ElementName::SwDataDefProps)?
362 .create_sub_element(ElementName::SwDataDefPropsVariants)?
363 .create_sub_element(ElementName::SwDataDefPropsConditional)?
364 .create_sub_element(ElementName::SwPointerTargetProps)?;
365 let contained_props = pointer_props
366 .create_sub_element(ElementName::SwDataDefProps)?
367 .create_sub_element(ElementName::SwDataDefPropsVariants)?
368 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
369 match target {
370 DataPointerTarget::BaseType(base_type) => {
371 contained_props
372 .create_sub_element(ElementName::BaseTypeRef)?
373 .set_reference_target(base_type.element())?;
374 pointer_props
375 .create_sub_element(ElementName::TargetCategory)
376 .and_then(|elem| elem.set_character_data("VALUE"))?;
377 }
378 DataPointerTarget::ImplementationDataType(impl_data_type) => {
379 contained_props
380 .create_sub_element(ElementName::ImplementationDataTypeRef)?
381 .set_reference_target(impl_data_type.element())?;
382 let target_category = impl_data_type
383 .category()
384 .as_ref()
385 .map(|item| item.to_string())
386 .unwrap_or("VALUE".to_string());
387 pointer_props
388 .create_sub_element(ElementName::TargetCategory)?
389 .set_character_data(target_category)?;
390 }
391 }
392 }
393 ImplementationDataTypeSettings::FunctionReference { .. } => {
394 element
395 .create_sub_element(ElementName::Category)?
396 .set_character_data("FUNCTION_REFERENCE")?;
397 }
398 ImplementationDataTypeSettings::TypeReference {
399 reftype,
400 compu_method,
401 data_constraint,
402 ..
403 } => {
404 element
405 .create_sub_element(ElementName::Category)?
406 .set_character_data("TYPE_REFERENCE")?;
407 let sw_data_def_props = element
408 .create_sub_element(ElementName::SwDataDefProps)?
409 .create_sub_element(ElementName::SwDataDefPropsVariants)?
410 .create_sub_element(ElementName::SwDataDefPropsConditional)?;
411 sw_data_def_props
412 .create_sub_element(ElementName::ImplementationDataTypeRef)?
413 .set_reference_target(reftype.element())?;
414 if let Some(compu_method) = compu_method {
415 sw_data_def_props
416 .create_sub_element(ElementName::CompuMethodRef)?
417 .set_reference_target(compu_method.element())?;
418 }
419 if let Some(data_constraint) = data_constraint {
420 sw_data_def_props
421 .create_sub_element(ElementName::DataConstrRef)?
422 .set_reference_target(data_constraint.element())?;
423 }
424 }
425 }
426
427 Ok(())
428}
429
430#[derive(Debug, Clone, PartialEq, Eq, Hash)]
434pub enum ImplementationDataCategory {
435 Value,
437 DataReference,
439 FunctionReference,
441 TypeReference,
443 Structure,
445 Union,
447 Array,
449}
450
451impl Display for ImplementationDataCategory {
452 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
453 match self {
454 ImplementationDataCategory::Value => f.write_str("VALUE"),
455 ImplementationDataCategory::DataReference => f.write_str("DATA_REFERENCE"),
456 ImplementationDataCategory::FunctionReference => f.write_str("FUNCTION_REFERENCE"),
457 ImplementationDataCategory::TypeReference => f.write_str("TYPE_REFERENCE"),
458 ImplementationDataCategory::Structure => f.write_str("STRUCTURE"),
459 ImplementationDataCategory::Union => f.write_str("UNION"),
460 ImplementationDataCategory::Array => f.write_str("ARRAY"),
461 }
462 }
463}
464
465impl TryFrom<&str> for ImplementationDataCategory {
466 type Error = AutosarAbstractionError;
467
468 fn try_from(value: &str) -> Result<Self, Self::Error> {
469 match value {
470 "VALUE" => Ok(ImplementationDataCategory::Value),
471 "DATA_REFERENCE" => Ok(ImplementationDataCategory::DataReference),
472 "FUNCTION_REFERENCE" => Ok(ImplementationDataCategory::FunctionReference),
473 "TYPE_REFERENCE" => Ok(ImplementationDataCategory::TypeReference),
474 "STRUCTURE" => Ok(ImplementationDataCategory::Structure),
475 "UNION" => Ok(ImplementationDataCategory::Union),
476 "ARRAY" => Ok(ImplementationDataCategory::Array),
477 _ => Err(AutosarAbstractionError::ValueConversionError {
478 value: value.to_string(),
479 dest: "ImplementationDataCategory".to_string(),
480 }),
481 }
482 }
483}
484
485#[derive(Debug, Clone, PartialEq, Eq, Hash)]
491pub enum ImplementationDataTypeSettings {
492 Value {
494 name: String,
496 base_type: SwBaseType,
498 compu_method: Option<CompuMethod>,
500 data_constraint: Option<DataConstr>,
502 },
503 Array {
505 name: String,
507 length: u32,
509 element_type: Box<ImplementationDataTypeSettings>,
511 },
512 Structure {
514 name: String,
516 elements: Vec<ImplementationDataTypeSettings>,
518 },
519 Union {
521 name: String,
523 elements: Vec<ImplementationDataTypeSettings>,
525 },
526 DataReference {
528 name: String,
530 target: DataPointerTarget,
532 },
533 FunctionReference {
535 name: String,
537 },
539 TypeReference {
541 name: String,
543 reftype: ImplementationDataType,
545 compu_method: Option<CompuMethod>,
547 data_constraint: Option<DataConstr>,
549 },
550}
551
552impl ImplementationDataTypeSettings {
553 #[must_use]
555 pub fn name(&self) -> &str {
556 match self {
557 ImplementationDataTypeSettings::Value { name, .. } => name,
558 ImplementationDataTypeSettings::Array { name, .. } => name,
559 ImplementationDataTypeSettings::Structure { name, .. } => name,
560 ImplementationDataTypeSettings::Union { name, .. } => name,
561 ImplementationDataTypeSettings::DataReference { name, .. } => name,
562 ImplementationDataTypeSettings::FunctionReference { name, .. } => name,
563 ImplementationDataTypeSettings::TypeReference { name, .. } => name,
564 }
565 }
566}
567
568#[derive(Debug, Clone, PartialEq, Eq, Hash)]
572pub enum DataPointerTarget {
573 BaseType(SwBaseType),
575 ImplementationDataType(ImplementationDataType),
577}
578
579#[cfg(test)]
582mod tests {
583 use super::*;
584 use crate::AutosarModelAbstraction;
585 use autosar_data::AutosarVersion;
586 use datatype::{BaseTypeEncoding, CompuMethodLinearContent, CompuScaleDirection};
587
588 #[test]
589 fn test_impl_data_type() {
590 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
591 let package = model.get_or_create_package("/DataTypes").unwrap();
592 let base_type =
593 SwBaseType::new("uint8", &package, 8, BaseTypeEncoding::None, None, None, Some("uint8")).unwrap();
594 let compu_method = CompuMethod::new(
595 "linear",
596 &package,
597 datatype::CompuMethodContent::Linear(CompuMethodLinearContent {
598 direction: CompuScaleDirection::IntToPhys,
599 offset: 42.0,
600 factor: 1.0,
601 divisor: 1.0,
602 lower_limit: None,
603 upper_limit: None,
604 }),
605 )
606 .unwrap();
607 let data_constraint = DataConstr::new("constraint", &package).unwrap();
608 let other_impl_data_type = ImplementationDataType::new(
609 &package,
610 &ImplementationDataTypeSettings::Value {
611 name: "OtherImplDataType".to_string(),
612 base_type: base_type.clone(),
613 compu_method: Some(compu_method.clone()),
614 data_constraint: None,
615 },
616 )
617 .unwrap();
618 let settings = ImplementationDataTypeSettings::Structure {
619 name: "Structure".to_string(),
620 elements: vec![
621 ImplementationDataTypeSettings::Union {
622 name: "union".to_string(),
623 elements: vec![ImplementationDataTypeSettings::Value {
624 name: "MyImplDataType1".to_string(),
625 base_type: base_type.clone(),
626 compu_method: Some(compu_method.clone()),
627 data_constraint: Some(data_constraint.clone()),
628 }],
629 },
630 ImplementationDataTypeSettings::Value {
631 name: "MyImplDataType1".to_string(),
632 base_type: base_type.clone(),
633 compu_method: Some(compu_method.clone()),
634 data_constraint: Some(data_constraint.clone()),
635 },
636 ImplementationDataTypeSettings::Array {
637 name: "MyArray".to_string(),
638 length: 10,
639 element_type: Box::new(ImplementationDataTypeSettings::Value {
640 name: "MyImplDataType2".to_string(),
641 base_type: base_type.clone(),
642 compu_method: Some(compu_method.clone()),
643 data_constraint: None,
644 }),
645 },
646 ImplementationDataTypeSettings::TypeReference {
647 name: "ReferenceType".to_string(),
648 reftype: other_impl_data_type.clone(),
649 compu_method: Some(compu_method.clone()),
650 data_constraint: Some(data_constraint.clone()),
651 },
652 ImplementationDataTypeSettings::DataReference {
653 name: "DataReferenceToBase".to_string(),
654 target: DataPointerTarget::BaseType(base_type.clone()),
655 },
656 ImplementationDataTypeSettings::DataReference {
657 name: "DataReferenceToImpl".to_string(),
658 target: DataPointerTarget::ImplementationDataType(other_impl_data_type.clone()),
659 },
660 ],
661 };
662 let impl_data_type = ImplementationDataType::new(&package, &settings).unwrap();
663
664 assert_eq!(impl_data_type.category(), Some(ImplementationDataCategory::Structure));
665
666 let sub_elements = impl_data_type.sub_elements().collect::<Vec<_>>();
667 assert_eq!(sub_elements.len(), 6);
668 assert_eq!(sub_elements[0].category(), Some(ImplementationDataCategory::Union));
669 assert_eq!(sub_elements[1].category(), Some(ImplementationDataCategory::Value));
670 assert_eq!(sub_elements[2].category(), Some(ImplementationDataCategory::Array));
671 assert_eq!(
672 sub_elements[3].category(),
673 Some(ImplementationDataCategory::TypeReference)
674 );
675 assert_eq!(
676 sub_elements[4].category(),
677 Some(ImplementationDataCategory::DataReference)
678 );
679 assert_eq!(
680 sub_elements[4].data_pointer_target(),
681 Some(DataPointerTarget::BaseType(base_type.clone()))
682 );
683 assert_eq!(
684 sub_elements[5].category(),
685 Some(ImplementationDataCategory::DataReference)
686 );
687 assert_eq!(
688 sub_elements[5].data_pointer_target(),
689 Some(DataPointerTarget::ImplementationDataType(other_impl_data_type.clone()))
690 );
691
692 let settings_read = impl_data_type.settings().unwrap();
693 assert_eq!(settings, settings_read);
694
695 let settings2 = ImplementationDataTypeSettings::Value {
697 name: "NewImplDataType".to_string(),
698 base_type,
699 compu_method: None,
700 data_constraint: None,
701 };
702 impl_data_type.apply_settings(&settings2).unwrap();
703 let settings_read = impl_data_type.settings().unwrap();
704 assert_eq!(settings2, settings_read);
705 }
706
707 #[test]
708 fn implementation_data_category() {
709 assert_eq!(ImplementationDataCategory::Value.to_string(), "VALUE");
710 assert_eq!(ImplementationDataCategory::DataReference.to_string(), "DATA_REFERENCE");
711 assert_eq!(
712 ImplementationDataCategory::FunctionReference.to_string(),
713 "FUNCTION_REFERENCE"
714 );
715 assert_eq!(ImplementationDataCategory::TypeReference.to_string(), "TYPE_REFERENCE");
716 assert_eq!(ImplementationDataCategory::Structure.to_string(), "STRUCTURE");
717 assert_eq!(ImplementationDataCategory::Union.to_string(), "UNION");
718 assert_eq!(ImplementationDataCategory::Array.to_string(), "ARRAY");
719
720 assert_eq!(
721 ImplementationDataCategory::try_from("VALUE").unwrap(),
722 ImplementationDataCategory::Value
723 );
724 assert_eq!(
725 ImplementationDataCategory::try_from("DATA_REFERENCE").unwrap(),
726 ImplementationDataCategory::DataReference
727 );
728 assert_eq!(
729 ImplementationDataCategory::try_from("FUNCTION_REFERENCE").unwrap(),
730 ImplementationDataCategory::FunctionReference
731 );
732 assert_eq!(
733 ImplementationDataCategory::try_from("TYPE_REFERENCE").unwrap(),
734 ImplementationDataCategory::TypeReference
735 );
736 assert_eq!(
737 ImplementationDataCategory::try_from("STRUCTURE").unwrap(),
738 ImplementationDataCategory::Structure
739 );
740 assert_eq!(
741 ImplementationDataCategory::try_from("UNION").unwrap(),
742 ImplementationDataCategory::Union
743 );
744 assert_eq!(
745 ImplementationDataCategory::try_from("ARRAY").unwrap(),
746 ImplementationDataCategory::Array
747 );
748
749 assert!(ImplementationDataCategory::try_from("invalid").is_err());
750 }
751}