autosar_data_abstraction/communication/cluster/
mod.rs

1use crate::{AbstractionElement, AutosarAbstractionError, IdentifiableAbstractionElement, System};
2use autosar_data::{Element, ElementName};
3
4mod can;
5mod ethernet;
6mod flexray;
7
8pub use can::*;
9pub use ethernet::*;
10pub use flexray::*;
11
12//##################################################################
13
14/// [`AbstractCluster`] defines the common interface for all supported communication clusters.
15pub trait AbstractCluster: AbstractionElement {
16    /// Returns the [`System`] the cluster is part of.
17    fn system(&self) -> Option<System> {
18        if let Ok(model) = self.element().model() {
19            let path = self.element().path().ok()?;
20            let refs = model.get_references_to(&path);
21
22            if let Some(system) = refs
23                .iter()
24                .filter_map(autosar_data::WeakElement::upgrade)
25                .filter(|elem| elem.element_name() == ElementName::FibexElementRef)
26                .filter_map(|elem| elem.named_parent().ok().flatten())
27                .find_map(|parent| System::try_from(parent).ok())
28            {
29                return Some(system);
30            }
31        }
32        None
33    }
34}
35
36//##################################################################
37
38/// A [`Cluster`] is returned by [`System::clusters`].
39/// It can contain any supported communication cluster.
40#[derive(Debug, Clone, PartialEq, Eq)]
41#[non_exhaustive]
42pub enum Cluster {
43    /// The Cluster is a [`CanCluster`]
44    Can(CanCluster),
45    /// The Cluster is an [`EthernetCluster`]
46    Ethernet(EthernetCluster),
47    /// The Cluster is a [`FlexrayCluster`]
48    FlexRay(FlexrayCluster),
49    // missing: Lin, TTCAN, J1939, CDD (aka user defined)
50}
51
52impl AbstractionElement for Cluster {
53    fn element(&self) -> &autosar_data::Element {
54        match self {
55            Cluster::Can(cancluster) => cancluster.element(),
56            Cluster::Ethernet(ethcluster) => ethcluster.element(),
57            Cluster::FlexRay(flxcluster) => flxcluster.element(),
58        }
59    }
60}
61
62impl IdentifiableAbstractionElement for Cluster {}
63impl AbstractCluster for Cluster {}
64
65impl TryFrom<Element> for Cluster {
66    type Error = AutosarAbstractionError;
67
68    fn try_from(element: Element) -> Result<Self, Self::Error> {
69        match element.element_name() {
70            ElementName::CanCluster => Ok(CanCluster::try_from(element)?.into()),
71            ElementName::EthernetCluster => Ok(EthernetCluster::try_from(element)?.into()),
72            ElementName::FlexrayCluster => Ok(FlexrayCluster::try_from(element)?.into()),
73            _ => Err(AutosarAbstractionError::ConversionError {
74                element,
75                dest: "Cluster".to_string(),
76            }),
77        }
78    }
79}
80
81impl From<CanCluster> for Cluster {
82    fn from(value: CanCluster) -> Self {
83        Cluster::Can(value)
84    }
85}
86
87impl From<EthernetCluster> for Cluster {
88    fn from(value: EthernetCluster) -> Self {
89        Cluster::Ethernet(value)
90    }
91}
92
93impl From<FlexrayCluster> for Cluster {
94    fn from(value: FlexrayCluster) -> Self {
95        Cluster::FlexRay(value)
96    }
97}
98
99//##################################################################
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use crate::AutosarModelAbstraction;
105    use autosar_data::AutosarVersion;
106
107    #[test]
108    fn cluster_system() {
109        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
110        let package = model.get_or_create_package("/Test").unwrap();
111        let system = package
112            .create_system("System", crate::SystemCategory::EcuExtract)
113            .unwrap();
114        let can_cluster = CanCluster::new("CanCluster", &package, None).unwrap();
115
116        assert!(can_cluster.system().is_none());
117        system.create_fibex_element_ref(can_cluster.element()).unwrap();
118        assert_eq!(can_cluster.system().unwrap(), system);
119    }
120
121    #[test]
122    fn cluster_conversion() {
123        let model = AutosarModelAbstraction::create("test.arxml", AutosarVersion::LATEST);
124        let package = model.get_or_create_package("/Test").unwrap();
125        let can_cluster = CanCluster::new("CanCluster", &package, None).unwrap();
126        let ethernet_cluster = EthernetCluster::new("EthernetCluster", &package).unwrap();
127        let flexray_settings = FlexrayClusterSettings::default();
128        let flexray_cluster = FlexrayCluster::new("FlexrayCluster", &package, &flexray_settings).unwrap();
129
130        let can: Cluster = can_cluster.into();
131        let ethernet: Cluster = ethernet_cluster.into();
132        let flexray: Cluster = flexray_cluster.into();
133
134        assert_eq!(can.element().item_name().unwrap(), "CanCluster");
135        assert_eq!(ethernet.element().item_name().unwrap(), "EthernetCluster");
136        assert_eq!(flexray.element().item_name().unwrap(), "FlexrayCluster");
137    }
138}