use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Facet {
pub name: String,
pub interface_type: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UsesPort {
pub name: String,
pub interface_type: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PortType {
pub name: String,
pub type_params: Vec<String>,
pub provides: Vec<Facet>,
pub uses: Vec<UsesPort>,
}
impl PortType {
#[must_use]
pub fn ami4ccm_port_type() -> Self {
Self {
name: "AMI4CCM_Port_Type".to_string(),
type_params: vec!["T".to_string(), "AMI4CCM_T".to_string()],
provides: vec![
Facet {
name: "ami4ccm_provides".to_string(),
interface_type: "AMI4CCM_T".to_string(),
},
Facet {
name: "ami4ccm_sync_provides".to_string(),
interface_type: "T".to_string(),
},
],
uses: vec![UsesPort {
name: "ami4ccm_uses".to_string(),
interface_type: "T".to_string(),
}],
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConnectorPort {
pub name: String,
pub port_type: String,
pub multiplex: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Connector {
pub name: String,
pub repository_id: String,
pub base: String,
pub type_args: Vec<String>,
pub ports: Vec<ConnectorPort>,
}
impl Connector {
#[must_use]
pub fn for_interface(original_iface: &str) -> Self {
let connector_name = format!("AMI4CCM_{original_iface}_Connector");
let ami_iface = format!("AMI4CCM_{original_iface}");
Self {
name: connector_name.clone(),
repository_id: format!("IDL:omg.org/CCM_AMI/{connector_name}:1.0"),
base: "Components::EnterpriseComponent".to_string(),
type_args: vec![original_iface.to_string(), ami_iface],
ports: vec![ConnectorPort {
name: "ami4ccm_port".to_string(),
port_type: "AMI4CCM_Port_Type".to_string(),
multiplex: false,
}],
}
}
pub fn enable_multiplex(&mut self) {
if let Some(port) = self.ports.iter_mut().find(|p| p.name == "ami4ccm_port") {
port.multiplex = true;
}
}
#[must_use]
pub fn is_local(&self) -> bool {
true
}
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
#[test]
fn port_type_matches_spec_annex_a_idl() {
let pt = PortType::ami4ccm_port_type();
assert_eq!(pt.type_params, vec!["T", "AMI4CCM_T"]);
assert_eq!(pt.provides.len(), 2);
assert_eq!(pt.provides[0].name, "ami4ccm_provides");
assert_eq!(pt.provides[0].interface_type, "AMI4CCM_T");
assert_eq!(pt.provides[1].name, "ami4ccm_sync_provides");
assert_eq!(pt.provides[1].interface_type, "T");
assert_eq!(pt.uses.len(), 1);
assert_eq!(pt.uses[0].name, "ami4ccm_uses");
assert_eq!(pt.uses[0].interface_type, "T");
}
#[test]
fn connector_for_interface_uses_correct_naming() {
let c = Connector::for_interface("StockManager");
assert_eq!(c.name, "AMI4CCM_StockManager_Connector");
assert_eq!(c.type_args, vec!["StockManager", "AMI4CCM_StockManager"]);
assert_eq!(
c.repository_id,
"IDL:omg.org/CCM_AMI/AMI4CCM_StockManager_Connector:1.0"
);
}
#[test]
fn connector_default_is_simplex() {
let c = Connector::for_interface("Foo");
assert!(!c.ports[0].multiplex);
}
#[test]
fn enable_multiplex_marks_port() {
let mut c = Connector::for_interface("Foo");
c.enable_multiplex();
assert!(c.ports[0].multiplex);
}
#[test]
fn connector_inherits_enterprise_component() {
let c = Connector::for_interface("Foo");
assert_eq!(c.base, "Components::EnterpriseComponent");
assert!(c.is_local());
}
}