dager 0.1.1

Crate to create and execute a graph of nodes.
Documentation
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

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)
    }
    //Checks if 
    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)
	}
    }
    //Checks if 
    fn all_set(&self) -> bool{
	self.value.is_some()
    }
}


/*
impl<A, B> InSignature for (InCol<A>, InCol<B>) where A: Send + 'static, B: Send + 'static{
    fn has_edge(&self, idx: usize) -> bool {
	match idx{
	    0 => self.0.edge.is_some(),
	    1 => self.1.edge.is_some(),
	    _ => false
	}
    }
    
    fn all_set(&self) -> bool {
	self.0.value.is_some() && self.1.value.is_some()
    }

    fn set_edge(&mut self, edge: Edge) -> Result<(), DErr> {
	match edge.end_idx{
	    0 => {
		if TypeId::of::<A>() != edge.type_id{
		    return Err(DErr::TypeMissmatch);
		}
		self.0.edge = Some(edge);
	    },
	    1 => {
		if TypeId::of::<B>() != edge.type_id{
		    return Err(DErr::TypeMissmatch);
		}
		self.1.edge = Some(edge);
	    },
	    _ => return Err(DErr::NoSuchPort),
	}
	Ok(())
    }

    fn set(&mut self, idx: usize, value: Box<dyn Any>) -> Result<(), DErr>{
	match idx{
	    0 => {
		match value.downcast::<A>(){
		    Ok(val) => self.0.value = Some(*val),
		    Err(_) => return Err(DErr::TypeMissmatch),
		}
		Ok(())
	    },
	    1 => {
		match value.downcast::<B>(){
		    Ok(val) => self.1.value = Some(*val),
		    Err(_) => return Err(DErr::TypeMissmatch),
		}
		Ok(())
	    },
	    _ => Err(DErr::NoSuchPort)
	}
    }
}
*/
///Implemets the InSignature trait for any tupel of the for (A, B, C, ...) denoted as impl_insig!(A:0, B:1, C:2, ...);
#[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);