autosar_data_abstraction/software_component/interface/
senderreceiver.rs

1use crate::{
2    AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
3    SenderReceiverToSignalMapping, abstraction_element,
4    datatype::{AbstractAutosarDataType, AutosarDataType, ValueSpecification},
5    get_reference_parents,
6    software_component::{AbstractPortInterface, DataReceivedEvent, PortPrototype},
7};
8use autosar_data::ElementName;
9
10//##################################################################
11
12/// A `SenderReceiverInterface` defines a set of data elements that can be sent and received
13///
14/// Use [`ArPackage::create_sender_receiver_interface`] to create a new sender receiver interface
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct SenderReceiverInterface(pub(crate) Element);
17abstraction_element!(SenderReceiverInterface, SenderReceiverInterface);
18impl IdentifiableAbstractionElement for SenderReceiverInterface {}
19impl AbstractPortInterface for SenderReceiverInterface {}
20
21impl SenderReceiverInterface {
22    /// Create a new `SenderReceiverInterface`
23    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
24        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
25        let sender_receiver_interface =
26            elements.create_named_sub_element(ElementName::SenderReceiverInterface, name)?;
27
28        Ok(Self(sender_receiver_interface))
29    }
30
31    /// remove this `SenderReceiverInterface` from the model
32    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
33        for data_element in self.data_elements() {
34            data_element.remove(true)?;
35        }
36
37        let ref_parents = get_reference_parents(self.element())?;
38
39        AbstractionElement::remove(self, deep)?;
40
41        for (named_parent, _parent) in ref_parents {
42            match named_parent.element_name() {
43                ElementName::PPortPrototype | ElementName::RPortPrototype | ElementName::PrPortPrototype => {
44                    if let Ok(port) = PortPrototype::try_from(named_parent) {
45                        port.remove(deep)?;
46                    }
47                }
48                _ => {}
49            }
50        }
51
52        Ok(())
53    }
54
55    /// Add a new data element to the sender receiver interface
56    pub fn create_data_element<T: AbstractAutosarDataType>(
57        &self,
58        name: &str,
59        data_type: &T,
60    ) -> Result<VariableDataPrototype, AutosarAbstractionError> {
61        let data_elements = self.element().get_or_create_sub_element(ElementName::DataElements)?;
62        VariableDataPrototype::new(name, &data_elements, data_type.element())
63    }
64
65    /// iterate over all data elements
66    pub fn data_elements(&self) -> impl Iterator<Item = VariableDataPrototype> + Send + use<> {
67        self.element()
68            .get_sub_element(ElementName::DataElements)
69            .into_iter()
70            .flat_map(|data_elements| data_elements.sub_elements())
71            .filter_map(|elem| VariableDataPrototype::try_from(elem).ok())
72    }
73}
74
75//##################################################################
76
77/// A `VariableDataPrototype` represents a data element in a `SenderReceiverInterface`
78#[derive(Debug, Clone, PartialEq, Eq, Hash)]
79pub struct VariableDataPrototype(Element);
80abstraction_element!(VariableDataPrototype, VariableDataPrototype);
81impl IdentifiableAbstractionElement for VariableDataPrototype {}
82
83impl VariableDataPrototype {
84    /// Create a new `VariableDataPrototype`
85    fn new(name: &str, parent_element: &Element, data_type: &Element) -> Result<Self, AutosarAbstractionError> {
86        let vdp = parent_element.create_named_sub_element(ElementName::VariableDataPrototype, name)?;
87        vdp.create_sub_element(ElementName::TypeTref)?
88            .set_reference_target(data_type)?;
89
90        Ok(Self(vdp))
91    }
92
93    /// Remove this `VariableDataPrototype` from the model
94    pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
95        let ref_parents = get_reference_parents(self.element())?;
96        AbstractionElement::remove(self, deep)?;
97
98        for (named_parent, parent) in ref_parents {
99            if named_parent.element_name() == ElementName::DataReceivedEvent {
100                if let Ok(event) = DataReceivedEvent::try_from(named_parent) {
101                    event.remove(deep)?;
102                }
103            } else if named_parent.element_name() == ElementName::SystemMapping
104                && parent.element_name() == ElementName::DataElementIref
105                && let Ok(Some(parent_parent)) = parent.parent()
106                && let Ok(mapping) = SenderReceiverToSignalMapping::try_from(parent_parent)
107            {
108                mapping.remove(deep)?;
109            }
110        }
111
112        Ok(())
113    }
114
115    /// Get the interface containing the data element
116    pub fn interface(&self) -> Result<SenderReceiverInterface, AutosarAbstractionError> {
117        let named_parent = self.element().named_parent()?.unwrap();
118        SenderReceiverInterface::try_from(named_parent)
119    }
120
121    /// Set the data type of the data element
122    pub fn set_data_type<T: AbstractAutosarDataType>(&self, data_type: &T) -> Result<(), AutosarAbstractionError> {
123        self.element()
124            .get_or_create_sub_element(ElementName::TypeTref)?
125            .set_reference_target(data_type.element())?;
126        Ok(())
127    }
128
129    /// Get the data type of the data element
130    #[must_use]
131    pub fn data_type(&self) -> Option<AutosarDataType> {
132        let type_tref = self.element().get_sub_element(ElementName::TypeTref)?;
133        AutosarDataType::try_from(type_tref.get_reference_target().ok()?).ok()
134    }
135
136    /// Set the init value of the data element
137    pub fn set_init_value<T: Into<ValueSpecification>>(
138        &self,
139        value_spec: Option<T>,
140    ) -> Result<(), AutosarAbstractionError> {
141        if let Some(value_spec) = value_spec {
142            let value_spec: ValueSpecification = value_spec.into();
143            let init_value_elem = self.element().get_or_create_sub_element(ElementName::InitValue)?;
144            value_spec.store(&init_value_elem)?;
145        } else {
146            let _ = self.element().remove_sub_element_kind(ElementName::InitValue);
147        }
148        Ok(())
149    }
150
151    /// Get the init value of the data element
152    #[must_use]
153    pub fn init_value(&self) -> Option<ValueSpecification> {
154        let init_value_elem = self
155            .element()
156            .get_sub_element(ElementName::InitValue)?
157            .get_sub_element_at(0)?;
158        ValueSpecification::load(&init_value_elem)
159    }
160}
161
162//##################################################################
163
164#[cfg(test)]
165mod test {
166    use crate::{
167        AutosarModelAbstraction,
168        datatype::{
169            AutosarDataType, BaseTypeEncoding, ImplementationDataTypeSettings, NumericalValueSpecification,
170            ValueSpecification,
171        },
172        software_component::{AbstractPortInterface, AbstractSwComponentType},
173    };
174    use autosar_data::AutosarVersion;
175
176    #[test]
177    fn sender_receiver_interface() {
178        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
179        let package = model.get_or_create_package("/package").unwrap();
180
181        let sr_interface = package
182            .create_sender_receiver_interface("SenderReceiverInterface")
183            .unwrap();
184
185        let base_type = package
186            .create_sw_base_type("base", 32, BaseTypeEncoding::None, None, None, None)
187            .unwrap();
188        let impl_settings = ImplementationDataTypeSettings::Value {
189            name: "ImplementationValue".to_string(),
190            base_type: base_type.clone(),
191            compu_method: None,
192            data_constraint: None,
193        };
194        let datatype = package.create_implementation_data_type(&impl_settings).unwrap();
195        let impl_settings2 = ImplementationDataTypeSettings::Value {
196            name: "ImplementationValue2".to_string(),
197            base_type,
198            compu_method: None,
199            data_constraint: None,
200        };
201        let datatype2 = package.create_implementation_data_type(&impl_settings2).unwrap();
202
203        let data_element = sr_interface.create_data_element("data_element", &datatype).unwrap();
204        assert_eq!(sr_interface.data_elements().count(), 1);
205        assert_eq!(data_element.interface().unwrap(), sr_interface);
206        assert_eq!(
207            data_element.data_type().unwrap(),
208            AutosarDataType::ImplementationDataType(datatype)
209        );
210        data_element.set_data_type(&datatype2).unwrap();
211        assert_eq!(
212            data_element.data_type().unwrap(),
213            AutosarDataType::ImplementationDataType(datatype2)
214        );
215
216        let value_spec = NumericalValueSpecification {
217            label: None,
218            value: 42.0,
219        };
220        data_element.set_init_value(Some(value_spec)).unwrap();
221        assert_eq!(
222            data_element.init_value().unwrap(),
223            NumericalValueSpecification {
224                label: None,
225                value: 42.0
226            }
227            .into()
228        );
229
230        data_element.set_init_value::<ValueSpecification>(None).unwrap();
231        assert!(data_element.init_value().is_none());
232
233        sr_interface.set_is_service(Some(false)).unwrap();
234        assert!(!sr_interface.is_service().unwrap());
235        sr_interface.set_is_service(Some(true)).unwrap();
236        assert!(sr_interface.is_service().unwrap());
237        sr_interface.set_is_service(None).unwrap();
238        assert_eq!(sr_interface.is_service(), None);
239    }
240
241    #[test]
242    fn remove() {
243        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
244        let package = model.get_or_create_package("/package").unwrap();
245        let sender_receiver_interface = package.create_sender_receiver_interface("TestInterface").unwrap();
246
247        let composition_type = package.create_composition_sw_component_type("comp_parent").unwrap();
248        let _composition_r_port = composition_type
249            .create_r_port("port_r", &sender_receiver_interface)
250            .unwrap();
251
252        assert_eq!(composition_type.ports().count(), 1);
253        sender_receiver_interface.remove(true).unwrap();
254        assert_eq!(composition_type.ports().count(), 0);
255    }
256}