use std::any::Any;
use std::any::TypeId;
use crate::DErr;
use crate::collections::InCol;
use crate::edge::Edge;
pub trait InSignature{
fn has_edge(&self, idx: usize) -> bool;
fn set(&mut self, idx: usize, value: Box<dyn Any>) -> Result<(), DErr>;
fn set_edge(&mut self, edge: Edge) -> Result<(), DErr>;
fn remove_edge(&mut self, port_idx: usize) -> Result<Edge, DErr>;
fn all_set(&self) -> bool;
}
impl InSignature for () {
fn has_edge(&self, _idx: usize) -> bool{
false
}
fn set(&mut self, _idx: usize, _value: Box<dyn Any>) -> Result<(), DErr>{
Err(DErr::NoSuchPort)
}
fn set_edge(&mut self, _edge: Edge) -> Result<(), DErr>{
Err(DErr::NoSuchPort)
}
fn remove_edge(&mut self, _port_idx: usize) -> Result<Edge, DErr>{
Err(DErr::NoSuchPort)
}
fn all_set(&self) -> bool{
true
}
}
impl<A> InSignature for InCol<A> where A: Send + 'static {
fn has_edge(&self, idx: usize) -> bool{
if idx == 0{
self.edge.is_some()
}else{
false
}
}
fn set(&mut self, idx: usize, value: Box<dyn Any>) -> Result<(), DErr>{
if idx == 0{
match value.downcast::<A>(){
Ok(val) => self.value = Some(*val),
Err(_) => return Err(DErr::TypeMissmatch),
}
Ok(())
}else{
Err(DErr::NoSuchPort)
}
}
fn set_edge(&mut self, edge: Edge) -> Result<(), DErr>{
if edge.end_idx == 0{
if TypeId::of::<A>() != edge.type_id{
return Err(DErr::TypeMissmatch);
}
self.edge = Some(edge);
Ok(())
}else{
Err(DErr::NoSuchPort)
}
}
fn remove_edge(&mut self, port_idx: usize) -> Result<Edge, DErr>{
if port_idx == 0{
if let Some(old_partner) = self.edge.take(){
Ok(old_partner)
}else{
Err(DErr::NoEdgeOnIdx)
}
}else{
Err(DErr::NoSuchPort)
}
}
fn all_set(&self) -> bool{
self.value.is_some()
}
}
#[macro_export]
macro_rules! impl_insig {
($($Gen:ident : $Idx:tt), +) => {
impl<$($Gen),+> InSignature for ($(InCol<$Gen>),+) where $($Gen : Send + 'static),+{
fn has_edge(&self, idx: usize) -> bool{
match idx{
$($Idx => self.$Idx.edge.is_some(),)+
_ => false
}
}
fn all_set(&self) -> bool{
$(self.$Idx.value.is_some() &&)+ true
}
fn set_edge(&mut self, edge: Edge) -> Result<(), DErr>{
match edge.end_idx{
$($Idx => {
if TypeId::of::<$Gen>() != edge.type_id{
return Err(DErr::TypeMissmatch);
}
self.$Idx.edge = Some(edge)
}),+
_ => return Err(DErr::NoSuchPort),
}
Ok(())
}
fn remove_edge(&mut self, port_idx: usize) -> Result<Edge, DErr>{
match port_idx{
$($Idx => {
if let Some(old_partner) = self.$Idx.edge.take(){
Ok(old_partner)
}else{
Err(DErr::NoEdgeOnIdx)
}
}),+
_ => Err(DErr::NoSuchPort)
}
}
fn set(&mut self, idx: usize, value: Box<dyn Any>) -> Result<(), DErr>{
match idx{
$($Idx => {
match value.downcast::<$Gen>(){
Ok(val) => self.$Idx.value = Some(*val),
Err(_) => return Err(DErr::TypeMissmatch),
}
Ok(())
}),+
_ => Err(DErr::NoSuchPort)
}
}
}
};
}
impl_insig!(A:0, B:1);
impl_insig!(A:0, B:1, C:2);
impl_insig!(A:0, B:1, C:2, D:3);
impl_insig!(A:0, B:1, C:2, D:3, E:4);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, W:22);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, W:22, X:23);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, W:22, X:23, Y:24);
impl_insig!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, Q:16, R:17, S:18, T:19, U:20, V:21, W:22, X:23, Y:24, Z:25);