autosar_data_abstraction/software_component/
port.rs

1use crate::{
2    AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3    software_component,
4};
5use autosar_data::{Element, ElementName};
6use software_component::{AbstractPortInterface, PortInterface, SwComponentType};
7
8//#########################################################
9
10/// `RPortPrototype` represents a required port prototype
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct RPortPrototype(Element);
13abstraction_element!(RPortPrototype, RPortPrototype);
14impl IdentifiableAbstractionElement for RPortPrototype {}
15
16impl RPortPrototype {
17    /// Create a new `RPortPrototype`
18    pub(crate) fn new<T: AbstractPortInterface>(
19        name: &str,
20        parent_element: &Element,
21        interface: &T,
22    ) -> Result<Self, AutosarAbstractionError> {
23        let r_port_prototype = parent_element.create_named_sub_element(ElementName::RPortPrototype, name)?;
24        r_port_prototype
25            .create_sub_element(ElementName::RequiredInterfaceTref)?
26            .set_reference_target(interface.element())?;
27
28        Ok(Self(r_port_prototype))
29    }
30
31    /// Get the port interface of the port prototype
32    pub fn port_interface(&self) -> Result<PortInterface, AutosarAbstractionError> {
33        let interface_elem = self
34            .element()
35            .get_sub_element(ElementName::RequiredInterfaceTref)
36            .and_then(|r| r.get_reference_target().ok())
37            .ok_or(AutosarAbstractionError::InvalidParameter(
38                "RPortPrototype is incomplete: RequiredInterfaceTref is missing".to_string(),
39            ))?;
40        PortInterface::try_from(interface_elem)
41    }
42
43    /// Get the component type containing the port prototype
44    pub fn component_type(&self) -> Result<SwComponentType, AutosarAbstractionError> {
45        let component_type_elem = self.element().named_parent()?.unwrap();
46        SwComponentType::try_from(component_type_elem)
47    }
48}
49
50//##################################################################
51
52/// `PPortPrototype` represents a provided port prototype
53#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54pub struct PPortPrototype(Element);
55abstraction_element!(PPortPrototype, PPortPrototype);
56impl IdentifiableAbstractionElement for PPortPrototype {}
57
58impl PPortPrototype {
59    /// Create a new `PPortPrototype`
60    pub(crate) fn new<T: AbstractPortInterface>(
61        name: &str,
62        parent_element: &Element,
63        interface: &T,
64    ) -> Result<Self, AutosarAbstractionError> {
65        let p_port_prototype = parent_element.create_named_sub_element(ElementName::PPortPrototype, name)?;
66        p_port_prototype
67            .create_sub_element(ElementName::ProvidedInterfaceTref)?
68            .set_reference_target(interface.element())?;
69
70        Ok(Self(p_port_prototype))
71    }
72
73    /// Get the port interface of the port prototype
74    pub fn port_interface(&self) -> Result<PortInterface, AutosarAbstractionError> {
75        let interface_elem = self
76            .element()
77            .get_sub_element(ElementName::ProvidedInterfaceTref)
78            .and_then(|r| r.get_reference_target().ok())
79            .ok_or(AutosarAbstractionError::InvalidParameter(
80                "PPortPrototype is incomplete: ProvidedInterfaceTref is missing".to_string(),
81            ))?;
82        PortInterface::try_from(interface_elem)
83    }
84
85    /// Get the component type containing the port prototype
86    pub fn component_type(&self) -> Result<SwComponentType, AutosarAbstractionError> {
87        let component_type_elem = self.element().named_parent()?.unwrap();
88        SwComponentType::try_from(component_type_elem)
89    }
90}
91
92//##################################################################
93
94/// `PRPortPrototype` represents a provided and required port prototype
95#[derive(Debug, Clone, PartialEq, Eq, Hash)]
96pub struct PRPortPrototype(Element);
97abstraction_element!(PRPortPrototype, PrPortPrototype);
98impl IdentifiableAbstractionElement for PRPortPrototype {}
99
100impl PRPortPrototype {
101    /// Create a new `PRPortPrototype`
102    pub(crate) fn new<T: AbstractPortInterface>(
103        name: &str,
104        parent_element: &Element,
105        interface: &T,
106    ) -> Result<Self, AutosarAbstractionError> {
107        if interface.element().element_name() == ElementName::ParameterInterface {
108            return Err(AutosarAbstractionError::InvalidParameter(
109                "ParameterInterface is not allowed for PRPortPrototype".to_string(),
110            ));
111        }
112
113        let pr_port_prototype = parent_element.create_named_sub_element(ElementName::PrPortPrototype, name)?;
114        pr_port_prototype
115            .create_sub_element(ElementName::ProvidedRequiredInterfaceTref)?
116            .set_reference_target(interface.element())?;
117
118        Ok(Self(pr_port_prototype))
119    }
120
121    /// Get the port interface of the port prototype
122    pub fn port_interface(&self) -> Result<PortInterface, AutosarAbstractionError> {
123        let interface_elem = self
124            .element()
125            .get_sub_element(ElementName::ProvidedRequiredInterfaceTref)
126            .and_then(|r| r.get_reference_target().ok())
127            .ok_or(AutosarAbstractionError::InvalidParameter(
128                "PRPortPrototype is incomplete: ProvidedRequiredInterfaceTref is missing".to_string(),
129            ))?;
130        PortInterface::try_from(interface_elem)
131    }
132
133    /// Get the component type containing the port prototype
134    pub fn component_type(&self) -> Result<SwComponentType, AutosarAbstractionError> {
135        let component_type_elem = self.element().named_parent()?.unwrap();
136        SwComponentType::try_from(component_type_elem)
137    }
138}
139
140//##################################################################
141
142/// The `PortPrototype` enum represents all possible kinds of port prototypes
143#[derive(Debug, Clone, PartialEq, Eq, Hash)]
144pub enum PortPrototype {
145    /// A required port prototype
146    R(RPortPrototype),
147    /// A provided port prototype
148    P(PPortPrototype),
149    /// A provided and required port prototype
150    PR(PRPortPrototype),
151}
152
153impl AbstractionElement for PortPrototype {
154    fn element(&self) -> &Element {
155        match self {
156            PortPrototype::R(port) => port.element(),
157            PortPrototype::P(port) => port.element(),
158            PortPrototype::PR(port) => port.element(),
159        }
160    }
161}
162
163impl IdentifiableAbstractionElement for PortPrototype {}
164
165impl From<RPortPrototype> for PortPrototype {
166    fn from(port: RPortPrototype) -> Self {
167        PortPrototype::R(port)
168    }
169}
170
171impl From<PPortPrototype> for PortPrototype {
172    fn from(port: PPortPrototype) -> Self {
173        PortPrototype::P(port)
174    }
175}
176
177impl From<PRPortPrototype> for PortPrototype {
178    fn from(port: PRPortPrototype) -> Self {
179        PortPrototype::PR(port)
180    }
181}
182
183impl TryFrom<Element> for PortPrototype {
184    type Error = AutosarAbstractionError;
185
186    fn try_from(element: Element) -> Result<Self, Self::Error> {
187        match element.element_name() {
188            ElementName::RPortPrototype => Ok(PortPrototype::R(RPortPrototype(element))),
189            ElementName::PPortPrototype => Ok(PortPrototype::P(PPortPrototype(element))),
190            ElementName::PrPortPrototype => Ok(PortPrototype::PR(PRPortPrototype(element))),
191            _ => Err(AutosarAbstractionError::ConversionError {
192                element: element.clone(),
193                dest: "PortPrototype".to_string(),
194            }),
195        }
196    }
197}
198
199impl PortPrototype {
200    /// Get the port interface of the port prototype
201    pub fn port_interface(&self) -> Result<PortInterface, AutosarAbstractionError> {
202        match self {
203            PortPrototype::R(port) => port.port_interface(),
204            PortPrototype::P(port) => port.port_interface(),
205            PortPrototype::PR(port) => port.port_interface(),
206        }
207    }
208
209    /// Get the component type containing the port prototype
210    pub fn component_type(&self) -> Result<SwComponentType, AutosarAbstractionError> {
211        let component_type_elem = self.element().named_parent()?.unwrap();
212        SwComponentType::try_from(component_type_elem)
213    }
214}
215
216//##################################################################
217
218/// `PortGroup` represents a group of ports
219#[derive(Debug, Clone, PartialEq, Eq, Hash)]
220pub struct PortGroup(Element);
221abstraction_element!(PortGroup, PortGroup);
222impl IdentifiableAbstractionElement for PortGroup {}
223
224impl PortGroup {
225    /// Create a new `PortGroup`
226    pub(crate) fn new(name: &str, parent_element: &Element) -> Result<Self, AutosarAbstractionError> {
227        let port_group = parent_element.create_named_sub_element(ElementName::PortGroup, name)?;
228
229        Ok(Self(port_group))
230    }
231}
232
233//##################################################################
234
235#[cfg(test)]
236mod test {
237    use super::*;
238    use crate::AutosarModelAbstraction;
239    use autosar_data::AutosarVersion;
240    use software_component::AbstractSwComponentType;
241
242    #[test]
243    fn ports() {
244        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
245        let package = model.get_or_create_package("/package").unwrap();
246
247        let comp = package.create_composition_sw_component_type("comp").unwrap();
248
249        let port_interface = package.create_sender_receiver_interface("sr_interface").unwrap();
250        let r_port = comp.create_r_port("sr_r_port", &port_interface).unwrap();
251        let p_port = comp.create_p_port("sr_p_port", &port_interface).unwrap();
252        let pr_port = comp.create_pr_port("sr_pr_port", &port_interface).unwrap();
253
254        assert_eq!(comp.ports().count(), 3);
255        let ports: Vec<PortPrototype> = comp.ports().collect();
256        assert_eq!(ports[0], r_port.clone().into());
257        assert_eq!(ports[1], p_port.clone().into());
258        assert_eq!(ports[2], pr_port.clone().into());
259        assert_eq!(r_port.component_type().unwrap(), comp.clone().into());
260        assert_eq!(p_port.component_type().unwrap(), comp.clone().into());
261        assert_eq!(pr_port.component_type().unwrap(), comp.clone().into());
262        assert_eq!(ports[0].component_type().unwrap(), comp.clone().into());
263
264        let port_interface = package.create_client_server_interface("cs_interface").unwrap();
265        let r_port = comp.create_r_port("cs_r_port", &port_interface).unwrap();
266        let p_port = comp.create_p_port("cs_p_port", &port_interface).unwrap();
267        let pr_port = comp.create_pr_port("cs_pr_port", &port_interface).unwrap();
268
269        assert_eq!(comp.ports().count(), 6);
270        let ports: Vec<PortPrototype> = comp.ports().collect();
271        assert_eq!(ports[3], r_port.into());
272        assert_eq!(ports[4], p_port.into());
273        assert_eq!(ports[5], pr_port.into());
274
275        let port_interface = package.create_mode_switch_interface("ms_interface").unwrap();
276        let r_port = comp.create_r_port("ms_r_port", &port_interface).unwrap();
277        let p_port = comp.create_p_port("ms_p_port", &port_interface).unwrap();
278        let pr_port = comp.create_pr_port("ms_pr_port", &port_interface).unwrap();
279
280        assert_eq!(comp.ports().count(), 9);
281        let ports: Vec<PortPrototype> = comp.ports().collect();
282        assert_eq!(ports[6], r_port.into());
283        assert_eq!(ports[7], p_port.into());
284        assert_eq!(ports[8], pr_port.into());
285
286        let port_interface = package.create_nv_data_interface("nv_interface").unwrap();
287        let r_port = comp.create_r_port("nv_r_port", &port_interface).unwrap();
288        let p_port = comp.create_p_port("nv_p_port", &port_interface).unwrap();
289        let pr_port = comp.create_pr_port("nv_pr_port", &port_interface).unwrap();
290
291        assert_eq!(comp.ports().count(), 12);
292        let ports: Vec<PortPrototype> = comp.ports().collect();
293        assert_eq!(ports[9], r_port.into());
294        assert_eq!(ports[10], p_port.into());
295        assert_eq!(ports[11], pr_port.into());
296
297        let port_interface = package.create_parameter_interface("param_interface").unwrap();
298        let r_port = comp.create_r_port("param_r_port", &port_interface).unwrap();
299        let p_port = comp.create_p_port("param_p_port", &port_interface).unwrap();
300        let pr_port_result = comp.create_pr_port("param_pr_port", &port_interface);
301        assert!(pr_port_result.is_err());
302
303        assert_eq!(comp.ports().count(), 14);
304        let ports: Vec<PortPrototype> = comp.ports().collect();
305        assert_eq!(ports[12], r_port.into());
306        assert_eq!(ports[13], p_port.into());
307
308        let port_interface = package.create_trigger_interface("trigger_interface").unwrap();
309        let r_port = comp.create_r_port("trigger_r_port", &port_interface).unwrap();
310        let p_port = comp.create_p_port("trigger_p_port", &port_interface).unwrap();
311        let pr_port = comp.create_pr_port("trigger_pr_port", &port_interface).unwrap();
312
313        assert_eq!(comp.ports().count(), 17);
314        let ports: Vec<PortPrototype> = comp.ports().collect();
315        assert_eq!(ports[14], r_port.into());
316        assert_eq!(ports[15], p_port.into());
317        assert_eq!(ports[16], pr_port.into());
318    }
319}