use serde::{Deserialize, Serialize};
use super::{ExtensionMap, Metadata};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase")]
pub struct PipelineInterface {
#[serde(default)]
pub inputs: Vec<InterfacePort>,
#[serde(default)]
pub outputs: Vec<InterfacePort>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
#[serde(default, flatten)]
pub extensions: ExtensionMap,
}
impl PipelineInterface {
pub fn input(&self, id: &str) -> Option<&InterfacePort> {
self.inputs.iter().find(|port| port.id == id)
}
pub fn output(&self, id: &str) -> Option<&InterfacePort> {
self.outputs.iter().find(|port| port.id == id)
}
pub fn all_ports(&self) -> impl Iterator<Item = &InterfacePort> {
self.inputs.iter().chain(self.outputs.iter())
}
pub fn has_unique_port_ids(&self) -> bool {
let mut seen = std::collections::BTreeSet::new();
self.all_ports().all(|port| seen.insert(port.id.as_str()))
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
#[serde(rename_all = "camelCase")]
pub struct InterfacePort {
pub id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contract_ref: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub purpose: Option<String>,
#[serde(default, flatten)]
pub extensions: ExtensionMap,
}
impl InterfacePort {
pub fn is_complete(&self) -> bool {
!self.id.trim().is_empty()
&& self
.name
.as_ref()
.is_some_and(|value| !value.trim().is_empty())
&& self
.contract_ref
.as_ref()
.is_some_and(|value| !value.trim().is_empty())
&& self
.purpose
.as_ref()
.is_some_and(|value| !value.trim().is_empty())
}
}