diff --git a/autosar-data-specification/src/lib.rs b/autosar-data-specification/src/lib.rs index a9b3388..6a599c7 100644 --- a/autosar-data-specification/src/lib.rs +++ b/autosar-data-specification/src/lib.rs @@ -552,6 +552,14 @@ impl ElementType { None } + /// verify that the given `dest_value` is a valid enum item that can be used to refer to this element type + #[must_use] + pub fn verify_reference_dest(&self, dest_value: EnumItem) -> bool { + let (start, end) = DATATYPES[self.typ as usize].ref_info; + let values = &REF_ITEMS[start as usize..end as usize]; + values.contains(&dest_value) + } + #[cfg(feature = "docstrings")] #[must_use] pub const fn docstring(&self) -> &'static str { @@ -1199,6 +1207,7 @@ mod test { let ref_value = physical_request_ref_type.reference_dest_value(&ident_type).unwrap(); assert_eq!(ref_value, EnumItem::TpConnectionIdent); + assert!(ident_type.verify_reference_dest(ref_value)); let invalid_ref = physical_request_ref_type.reference_dest_value(&tp_connections_type); assert!(invalid_ref.is_none()); } diff --git a/autosar-data/src/autosarmodel.rs b/autosar-data/src/autosarmodel.rs index eb4f8b5..2d5aebe 100644 --- a/autosar-data/src/autosarmodel.rs +++ b/autosar-data/src/autosarmodel.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, hash::Hash, str::FromStr}; +use std::{collections::HashMap, hash::Hash}; use crate::*; @@ -780,18 +780,12 @@ impl AutosarModel { if let Some(target_elem) = target_elem_weak.upgrade() { // the target of the reference exists, but the reference can still be technically invalid // if the content of the DEST attribute on the reference is wrong - let target_elemname = target_elem.element_name(); - // e.g. if the target is a , then the reference must have the attribute DEST="SYSTEM". - // Converting the ElementName of the target_elem to an EnumItem for use in the DEST attribute - // is done by converting ElementName -> str -> EnumItem - let required_reftype = EnumItem::from_str(target_elemname.to_str()).unwrap(); - for referring_elem_weak in element_list { if let Some(referring_elem) = referring_elem_weak.upgrade() { - if let Some(CharacterData::Enum(reftype)) = + if let Some(CharacterData::Enum(dest_value)) = referring_elem.attribute_value(AttributeName::Dest) { - if reftype != required_reftype { + if target_elem.element_type().verify_reference_dest(dest_value) { // wrong reference type in the DEST attribute broken_refs.push(referring_elem_weak.clone()); } diff --git a/autosar-data/src/element.rs b/autosar-data/src/element.rs index 3518514..c1f4d6f 100644 --- a/autosar-data/src/element.rs +++ b/autosar-data/src/element.rs @@ -836,20 +836,12 @@ impl Element { .get_element_by_path(&reference) .ok_or(AutosarDataError::InvalidReference)?; - let dest = self + let dest_value = self .attribute_value(AttributeName::Dest) - .map(|cdata| cdata.to_string()) + .and_then(|cdata| cdata.enum_value()) .ok_or(AutosarDataError::InvalidReference)?; - if dest == target_elem.element_name().to_str() { - // common case: the value of DEST is equal to the element name of the target + if target_elem.element_type().verify_reference_dest(dest_value) { Ok(target_elem) - } else if let Some(refval) = self.element_type().reference_dest_value(&target_elem.element_type()) { - // uncommon: find a correct DEST value in the specification - if refval.to_string() == dest { - Ok(target_elem) - } else { - Err(AutosarDataError::InvalidReference) - } } else { Err(AutosarDataError::InvalidReference) }