autosar_data_abstraction/software_component/interface/
senderreceiver.rs

1use crate::{
2    AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
3    abstraction_element,
4    datatype::{AbstractAutosarDataType, AutosarDataType, ValueSpecification},
5    software_component::AbstractPortInterface,
6};
7use autosar_data::ElementName;
8
9//##################################################################
10
11/// A `SenderReceiverInterface` defines a set of data elements that can be sent and received
12///
13/// Use [`ArPackage::create_sender_receiver_interface`] to create a new sender receiver interface
14#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct SenderReceiverInterface(pub(crate) Element);
16abstraction_element!(SenderReceiverInterface, SenderReceiverInterface);
17impl IdentifiableAbstractionElement for SenderReceiverInterface {}
18impl AbstractPortInterface for SenderReceiverInterface {}
19
20impl SenderReceiverInterface {
21    /// Create a new `SenderReceiverInterface`
22    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
23        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
24        let sender_receiver_interface =
25            elements.create_named_sub_element(ElementName::SenderReceiverInterface, name)?;
26
27        Ok(Self(sender_receiver_interface))
28    }
29
30    /// Add a new data element to the sender receiver interface
31    pub fn create_data_element<T: AbstractAutosarDataType>(
32        &self,
33        name: &str,
34        data_type: &T,
35    ) -> Result<VariableDataPrototype, AutosarAbstractionError> {
36        let data_elements = self.element().get_or_create_sub_element(ElementName::DataElements)?;
37        VariableDataPrototype::new(name, &data_elements, data_type.element())
38    }
39
40    /// iterate over all data elements
41    pub fn data_elements(&self) -> impl Iterator<Item = VariableDataPrototype> + Send + 'static {
42        self.element()
43            .get_sub_element(ElementName::DataElements)
44            .into_iter()
45            .flat_map(|data_elements| data_elements.sub_elements())
46            .filter_map(|elem| VariableDataPrototype::try_from(elem).ok())
47    }
48}
49
50//##################################################################
51
52/// A `VariableDataPrototype` represents a data element in a `SenderReceiverInterface`
53#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54pub struct VariableDataPrototype(Element);
55abstraction_element!(VariableDataPrototype, VariableDataPrototype);
56impl IdentifiableAbstractionElement for VariableDataPrototype {}
57
58impl VariableDataPrototype {
59    /// Create a new `VariableDataPrototype`
60    fn new(name: &str, parent_element: &Element, data_type: &Element) -> Result<Self, AutosarAbstractionError> {
61        let vdp = parent_element.create_named_sub_element(ElementName::VariableDataPrototype, name)?;
62        vdp.create_sub_element(ElementName::TypeTref)?
63            .set_reference_target(data_type)?;
64
65        Ok(Self(vdp))
66    }
67
68    /// Get the interface containing the data element
69    pub fn interface(&self) -> Result<SenderReceiverInterface, AutosarAbstractionError> {
70        let named_parent = self.element().named_parent()?.unwrap();
71        SenderReceiverInterface::try_from(named_parent)
72    }
73
74    /// Set the data type of the data element
75    pub fn set_data_type<T: AbstractAutosarDataType>(&self, data_type: &T) -> Result<(), AutosarAbstractionError> {
76        self.element()
77            .get_or_create_sub_element(ElementName::TypeTref)?
78            .set_reference_target(data_type.element())?;
79        Ok(())
80    }
81
82    /// Get the data type of the data element
83    #[must_use]
84    pub fn data_type(&self) -> Option<AutosarDataType> {
85        let type_tref = self.element().get_sub_element(ElementName::TypeTref)?;
86        AutosarDataType::try_from(type_tref.get_reference_target().ok()?).ok()
87    }
88
89    /// Set the init value of the data element
90    pub fn set_init_value<T: Into<ValueSpecification>>(
91        &self,
92        value_spec: Option<T>,
93    ) -> Result<(), AutosarAbstractionError> {
94        if let Some(value_spec) = value_spec {
95            let value_spec: ValueSpecification = value_spec.into();
96            let init_value_elem = self.element().get_or_create_sub_element(ElementName::InitValue)?;
97            value_spec.store(&init_value_elem)?;
98        } else {
99            let _ = self.element().remove_sub_element_kind(ElementName::InitValue);
100        }
101        Ok(())
102    }
103
104    /// Get the init value of the data element
105    #[must_use]
106    pub fn init_value(&self) -> Option<ValueSpecification> {
107        let init_value_elem = self
108            .element()
109            .get_sub_element(ElementName::InitValue)?
110            .get_sub_element_at(0)?;
111        ValueSpecification::load(&init_value_elem)
112    }
113}
114
115//##################################################################
116
117#[cfg(test)]
118mod test {
119    use crate::{
120        AutosarModelAbstraction,
121        datatype::{
122            AutosarDataType, BaseTypeEncoding, ImplementationDataTypeSettings, NumericalValueSpecification,
123            ValueSpecification,
124        },
125        software_component::AbstractPortInterface,
126    };
127    use autosar_data::AutosarVersion;
128
129    #[test]
130    fn sender_receiver_interface() {
131        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
132        let package = model.get_or_create_package("/package").unwrap();
133
134        let sr_interface = package
135            .create_sender_receiver_interface("SenderReceiverInterface")
136            .unwrap();
137
138        let base_type = package
139            .create_sw_base_type("base", 32, BaseTypeEncoding::None, None, None, None)
140            .unwrap();
141        let impl_settings = ImplementationDataTypeSettings::Value {
142            name: "ImplementationValue".to_string(),
143            base_type: base_type.clone(),
144            compu_method: None,
145            data_constraint: None,
146        };
147        let datatype = package.create_implementation_data_type(&impl_settings).unwrap();
148        let impl_settings2 = ImplementationDataTypeSettings::Value {
149            name: "ImplementationValue2".to_string(),
150            base_type,
151            compu_method: None,
152            data_constraint: None,
153        };
154        let datatype2 = package.create_implementation_data_type(&impl_settings2).unwrap();
155
156        let data_element = sr_interface.create_data_element("data_element", &datatype).unwrap();
157        assert_eq!(sr_interface.data_elements().count(), 1);
158        assert_eq!(data_element.interface().unwrap(), sr_interface);
159        assert_eq!(
160            data_element.data_type().unwrap(),
161            AutosarDataType::ImplementationDataType(datatype)
162        );
163        data_element.set_data_type(&datatype2).unwrap();
164        assert_eq!(
165            data_element.data_type().unwrap(),
166            AutosarDataType::ImplementationDataType(datatype2)
167        );
168
169        let value_spec = NumericalValueSpecification {
170            label: None,
171            value: 42.0,
172        };
173        data_element.set_init_value(Some(value_spec)).unwrap();
174        assert_eq!(
175            data_element.init_value().unwrap(),
176            NumericalValueSpecification {
177                label: None,
178                value: 42.0
179            }
180            .into()
181        );
182
183        data_element.set_init_value::<ValueSpecification>(None).unwrap();
184        assert!(data_element.init_value().is_none());
185
186        sr_interface.set_is_service(Some(false)).unwrap();
187        assert!(!sr_interface.is_service().unwrap());
188        sr_interface.set_is_service(Some(true)).unwrap();
189        assert!(sr_interface.is_service().unwrap());
190        sr_interface.set_is_service(None).unwrap();
191        assert_eq!(sr_interface.is_service(), None);
192    }
193}