autosar_data_abstraction/software_component/interface/
mod.rs

1use crate::{
2    AbstractionElement, ArPackage, AutosarAbstractionError, Element, IdentifiableAbstractionElement,
3    abstraction_element,
4};
5use autosar_data::ElementName;
6
7mod clientserver;
8mod senderreceiver;
9
10pub use clientserver::*;
11pub use senderreceiver::*;
12
13//##################################################################
14
15/// A `ModeSwitchInterface` defines a set of modes that can be switched
16///
17/// Use [`ArPackage::create_mode_switch_interface`] to create a new mode switch interface
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
19pub struct ModeSwitchInterface(Element);
20abstraction_element!(ModeSwitchInterface, ModeSwitchInterface);
21impl IdentifiableAbstractionElement for ModeSwitchInterface {}
22impl AbstractPortInterface for ModeSwitchInterface {}
23
24impl ModeSwitchInterface {
25    /// Create a new `ModeSwitchInterface`
26    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
27        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
28        let mode_switch_interface = elements.create_named_sub_element(ElementName::ModeSwitchInterface, name)?;
29
30        Ok(Self(mode_switch_interface))
31    }
32}
33
34//##################################################################
35
36/// A `ParameterInterface` defines a set of parameters that can be accessed
37///
38/// Use [`ArPackage::create_parameter_interface`] to create a new parameter interface
39#[derive(Debug, Clone, PartialEq, Eq, Hash)]
40pub struct ParameterInterface(Element);
41abstraction_element!(ParameterInterface, ParameterInterface);
42impl IdentifiableAbstractionElement for ParameterInterface {}
43impl AbstractPortInterface for ParameterInterface {}
44
45impl ParameterInterface {
46    /// Create a new `ParameterInterface`
47    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
48        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
49        let parameter_interface = elements.create_named_sub_element(ElementName::ParameterInterface, name)?;
50
51        Ok(Self(parameter_interface))
52    }
53}
54
55//##################################################################
56
57/// An `NvDataInterface` defines non-volatile data that can be accessed through the interface
58///
59/// Use [`ArPackage::create_nv_data_interface`] to create a new non-volatile data interface
60#[derive(Debug, Clone, PartialEq, Eq, Hash)]
61pub struct NvDataInterface(Element);
62abstraction_element!(NvDataInterface, NvDataInterface);
63impl IdentifiableAbstractionElement for NvDataInterface {}
64impl AbstractPortInterface for NvDataInterface {}
65
66impl NvDataInterface {
67    /// Create a new `NvDataInterface`
68    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
69        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
70        let nv_data_interface = elements.create_named_sub_element(ElementName::NvDataInterface, name)?;
71
72        Ok(Self(nv_data_interface))
73    }
74}
75
76//##################################################################
77
78/// A `TriggerInterface` declares a number of triggers that can be sent by an trigger source
79///
80/// Use [`ArPackage::create_trigger_interface`] to create a new trigger interface
81#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub struct TriggerInterface(Element);
83abstraction_element!(TriggerInterface, TriggerInterface);
84impl IdentifiableAbstractionElement for TriggerInterface {}
85impl AbstractPortInterface for TriggerInterface {}
86
87impl TriggerInterface {
88    /// Create a new `TriggerInterface`
89    pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
90        let elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
91        let trigger_interface = elements.create_named_sub_element(ElementName::TriggerInterface, name)?;
92
93        Ok(Self(trigger_interface))
94    }
95}
96
97//##################################################################
98
99/// The `AbstractPortInterface` trait is a marker trait for all port interfaces
100pub trait AbstractPortInterface: AbstractionElement {}
101
102//##################################################################
103
104/// The `PortInterface` enum represents all possible port interfaces
105#[derive(Debug, Clone, PartialEq, Eq, Hash)]
106pub enum PortInterface {
107    /// The interface is a sender-receiver interface
108    SenderReceiverInterface(SenderReceiverInterface),
109    /// The interface is a client-server interface
110    ClientServerInterface(ClientServerInterface),
111    /// The interface is a mode switch interface
112    ModeSwitchInterface(ModeSwitchInterface),
113    /// The interface is a parameter interface
114    ParameterInterface(ParameterInterface),
115    /// The interface is a non-volatile data interface
116    NvDataInterface(NvDataInterface),
117    /// The interface is a trigger interface
118    TriggerInterface(TriggerInterface),
119}
120
121impl AbstractionElement for PortInterface {
122    fn element(&self) -> &Element {
123        match self {
124            PortInterface::SenderReceiverInterface(sender_receiver_interface) => sender_receiver_interface.element(),
125            PortInterface::ClientServerInterface(client_server_interface) => client_server_interface.element(),
126            PortInterface::ModeSwitchInterface(mode_switch_interface) => mode_switch_interface.element(),
127            PortInterface::ParameterInterface(parameter_interface) => parameter_interface.element(),
128            PortInterface::NvDataInterface(nv_data_interface) => nv_data_interface.element(),
129            PortInterface::TriggerInterface(trigger_interface) => trigger_interface.element(),
130        }
131    }
132}
133
134impl IdentifiableAbstractionElement for PortInterface {}
135impl AbstractPortInterface for PortInterface {}
136
137impl TryFrom<Element> for PortInterface {
138    type Error = AutosarAbstractionError;
139
140    fn try_from(element: Element) -> Result<Self, Self::Error> {
141        match element.element_name() {
142            ElementName::SenderReceiverInterface => {
143                Ok(PortInterface::SenderReceiverInterface(SenderReceiverInterface(element)))
144            }
145            ElementName::ClientServerInterface => {
146                Ok(PortInterface::ClientServerInterface(ClientServerInterface(element)))
147            }
148            ElementName::ModeSwitchInterface => Ok(PortInterface::ModeSwitchInterface(ModeSwitchInterface(element))),
149            ElementName::ParameterInterface => Ok(PortInterface::ParameterInterface(ParameterInterface(element))),
150            ElementName::NvDataInterface => Ok(PortInterface::NvDataInterface(NvDataInterface(element))),
151            ElementName::TriggerInterface => Ok(PortInterface::TriggerInterface(TriggerInterface(element))),
152            _ => Err(AutosarAbstractionError::ConversionError {
153                element,
154                dest: "PortInterface".to_string(),
155            }),
156        }
157    }
158}
159
160//##################################################################
161
162#[cfg(test)]
163mod test {
164    use super::*;
165    use crate::{AutosarModelAbstraction, software_component::AbstractSwComponentType};
166    use autosar_data::AutosarVersion;
167
168    #[test]
169    fn test_interfaces() {
170        let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
171        let package = model.get_or_create_package("/package").unwrap();
172
173        let sender_receiver_interface = package
174            .create_sender_receiver_interface("sender_receiver_interface")
175            .unwrap();
176        let client_server_interface = package
177            .create_client_server_interface("client_server_interface")
178            .unwrap();
179        let mode_switch_interface = package.create_mode_switch_interface("mode_switch_interface").unwrap();
180        let parameter_interface = package.create_parameter_interface("parameter_interface").unwrap();
181        let nv_data_interface = package.create_nv_data_interface("nv_data_interface").unwrap();
182        let trigger_interface = package.create_trigger_interface("trigger_interface").unwrap();
183
184        let composition = package.create_composition_sw_component_type("composition").unwrap();
185
186        let port_1 = composition.create_p_port("port_1", &sender_receiver_interface).unwrap();
187        assert!(matches!(
188            port_1.port_interface(),
189            Ok(PortInterface::SenderReceiverInterface(interface)) if interface == sender_receiver_interface
190        ));
191        assert_eq!(
192            port_1.port_interface().unwrap().element(),
193            sender_receiver_interface.element()
194        );
195
196        let port_2 = composition.create_p_port("port_2", &client_server_interface).unwrap();
197        assert!(matches!(
198            port_2.port_interface(),
199            Ok(PortInterface::ClientServerInterface(interface)) if interface == client_server_interface
200        ));
201        assert_eq!(
202            port_2.port_interface().unwrap().element(),
203            client_server_interface.element()
204        );
205
206        let port_3 = composition.create_p_port("port_3", &mode_switch_interface).unwrap();
207        assert!(matches!(
208            port_3.port_interface(),
209            Ok(PortInterface::ModeSwitchInterface(interface)) if interface == mode_switch_interface
210        ));
211        assert_eq!(
212            port_3.port_interface().unwrap().element(),
213            mode_switch_interface.element()
214        );
215
216        let port_4 = composition.create_p_port("port_4", &parameter_interface).unwrap();
217        assert!(matches!(
218            port_4.port_interface(),
219            Ok(PortInterface::ParameterInterface(interface)) if interface == parameter_interface
220        ));
221        assert_eq!(
222            port_4.port_interface().unwrap().element(),
223            parameter_interface.element()
224        );
225
226        let port_5 = composition.create_p_port("port_5", &nv_data_interface).unwrap();
227        assert!(matches!(
228            port_5.port_interface(),
229            Ok(PortInterface::NvDataInterface(interface)) if interface == nv_data_interface
230        ));
231        assert_eq!(port_5.port_interface().unwrap().element(), nv_data_interface.element());
232
233        let port_6 = composition.create_p_port("port_6", &trigger_interface).unwrap();
234        assert!(matches!(
235            port_6.port_interface(),
236            Ok(PortInterface::TriggerInterface(interface)) if interface == trigger_interface
237        ));
238        assert_eq!(port_6.port_interface().unwrap().element(), trigger_interface.element());
239    }
240}