#![allow(unused)]
use crate::{
any_port_value::AnyPortValue,
bind::{
BindCommons, BindIn, BindInOut, BindOut,
bound_value::{BoundValueReadGuard, BoundValueWriteGuard},
in_::InBound,
in_out::InOutBound,
out_::OutBound,
},
collections::PortCollection,
error::Error,
};
const INPUT_TYPE: &str = "input_port";
const OUTPUT_TYPE: &str = "output_port";
const INOUT_TYPE: &str = "inout_port";
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone)]
pub enum PortVariant {
InBound(InBound),
InOutBound(InOutBound),
OutBound(OutBound),
}
impl PortVariant {
pub fn create_inbound<T: AnyPortValue>(value: T) -> Self {
Self::InBound(InBound::with_value(value))
}
pub fn create_inoutbound<T: AnyPortValue>(value: T) -> Self {
Self::InOutBound(InOutBound::with_value(value))
}
pub fn create_outbound<T: AnyPortValue>(value: T) -> Self {
Self::OutBound(OutBound::with_value(value))
}
pub fn create_inbound_parseable<T: AnyPortValue + core::str::FromStr>(value: T) -> Self {
Self::InBound(InBound::with_value_parseable(value))
}
pub fn create_inoutbound_parseable<T: AnyPortValue + core::str::FromStr>(value: T) -> Self {
Self::InOutBound(InOutBound::with_value_parseable(value))
}
pub fn create_outbound_parseable<T: AnyPortValue + core::str::FromStr>(value: T) -> Self {
Self::OutBound(OutBound::with_value_parseable(value))
}
pub fn use_from_bound(&mut self, bound: &dyn BindCommons) -> Result<(), Error> {
match self {
Self::InBound(port) => port.use_from_bound(bound),
Self::InOutBound(port) => port.use_from_bound(bound),
Self::OutBound(port) => port.use_from_bound(bound),
}
}
pub fn use_from_variant(&mut self, other: &PortVariant) -> Result<(), Error> {
match other {
Self::InBound(bound) => self.use_from_bound(bound),
Self::InOutBound(bound) => self.use_from_bound(bound),
Self::OutBound(bound) => self.use_from_bound(bound),
}
}
pub fn use_from_collection(&mut self, collection: &dyn PortCollection, name: &str) -> Result<(), Error> {
if let Some(variant) = collection.find(name) {
self.use_from_variant(variant)
} else {
Err(Error::OtherNotFound { name: name.into() })
}
}
pub fn get<T: AnyPortValue + Clone>(&self) -> Result<Option<T>, Error> {
match self {
Self::InBound(port) => port.get(),
Self::InOutBound(port) => port.get(),
Self::OutBound(_) => Err(Error::PortType),
}
}
pub fn is<T: AnyPortValue>(&self) -> bool {
match self {
Self::InBound(port) => port.is::<T>(),
Self::InOutBound(port) => port.is::<T>(),
Self::OutBound(port) => port.is::<T>(),
}
}
pub fn read<T: AnyPortValue>(&self) -> Result<BoundValueReadGuard<T>, Error> {
match self {
Self::InBound(port) => port.read(),
Self::InOutBound(port) => port.read(),
Self::OutBound(_) => Err(Error::PortType),
}
}
pub fn try_read<T: AnyPortValue>(&self) -> Result<BoundValueReadGuard<T>, Error> {
match self {
Self::InBound(port) => port.try_read(),
Self::InOutBound(port) => port.try_read(),
Self::OutBound(_) => Err(Error::PortType),
}
}
pub fn replace<T: AnyPortValue>(&mut self, value: T) -> Result<Option<T>, Error> {
match self {
Self::InOutBound(port) => port.replace(value),
Self::InBound(_) | Self::OutBound(_) => Err(Error::PortType),
}
}
pub fn sequence_number(&self) -> u32 {
match self {
Self::InBound(port) => port.sequence_number(),
Self::InOutBound(port) => port.sequence_number(),
Self::OutBound(port) => port.sequence_number(),
}
}
pub fn take<T: AnyPortValue>(&mut self) -> Result<Option<T>, Error> {
match self {
Self::InOutBound(port) => port.take(),
Self::InBound(_) | Self::OutBound(_) => Err(Error::PortType),
}
}
pub fn set<T: AnyPortValue>(&mut self, value: T) -> Result<(), Error> {
match self {
Self::OutBound(port) => port.set(value),
Self::InOutBound(port) => port.set(value),
Self::InBound(_) => Err(Error::PortType),
}
}
pub fn set_from_str(&mut self, s: &str) -> Result<(), Error> {
match self {
Self::OutBound(port) => port.init_from_str(s),
Self::InOutBound(port) => port.init_from_str(s),
Self::InBound(port) => port.init_from_str(s), }
}
pub fn write<T: AnyPortValue>(&mut self) -> Result<BoundValueWriteGuard<T>, Error> {
match self {
Self::OutBound(port) => port.write(),
Self::InOutBound(port) => port.write(),
Self::InBound(_) => Err(Error::PortType),
}
}
pub fn try_write<T: AnyPortValue>(&mut self) -> Result<BoundValueWriteGuard<T>, Error> {
match self {
Self::OutBound(port) => port.try_write(),
Self::InOutBound(port) => port.try_write(),
Self::InBound(_) => Err(Error::PortType),
}
}
pub fn into_inner<T: AnyPortValue>(self) -> Result<Option<T>, Error> {
match self {
Self::InBound(port) => port.into_inner(),
Self::InOutBound(port) => port.into_inner(),
Self::OutBound(port) => port.into_inner(),
}
}
pub fn to_in_out(self) -> PortVariant {
match self {
Self::InOutBound(_) => self,
Self::InBound(port) => Self::InOutBound(InOutBound::from_value(port.value())),
Self::OutBound(port) => Self::InOutBound(InOutBound::from_value(port.value())),
}
}
#[must_use]
pub const fn direction(&self) -> &'static str {
match self {
Self::InOutBound(_) => INOUT_TYPE,
Self::InBound(_) => INPUT_TYPE,
Self::OutBound(_) => OUTPUT_TYPE,
}
}
#[must_use]
pub fn data_type(&self) -> &str {
match self {
Self::InOutBound(port) => port.data_type(),
Self::InBound(port) => port.data_type(),
Self::OutBound(port) => port.data_type(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const fn is_normal<T: Sized + Send + Sync>() {}
#[test]
const fn normal_types() {
is_normal::<&PortVariant>();
is_normal::<PortVariant>();
}
}