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::TypeId;
use std::sync::Arc;

use log::error;

use crate::DErr;
use crate::collections::InCol;
use crate::collections::OutCol;
use crate::executor::Executor;
use crate::executor::Task;
use crate::inport::InSignature;
use crate::outport::OutSignature;

pub trait IntoIoSignature{
    type InSig: InSignature;
    type OutSig: OutSignature;
    fn into_in_collection() -> Self::InSig;
    fn into_out_collection() -> Self::OutSig;
    fn send(self, executor: Arc<Executor>, out_signature: &Self::OutSig) -> Result<(), DErr>;
    fn from_collection(collection: &mut Self::InSig) -> Self;
    fn get_type_id(idx: usize) -> Option<TypeId>;
}

impl IntoIoSignature for (){
    type InSig = ();
    type OutSig = ();
    fn into_in_collection() -> Self::InSig {}
    fn into_out_collection() -> Self::OutSig {}
    fn send(self, _executor: Arc<Executor>, _out_signature: &Self::OutSig) -> Result<(), DErr> {
	Ok(())
    }

    fn from_collection(_collection: &mut Self::InSig) -> Self {}
    fn get_type_id(_idx: usize) -> Option<TypeId> {None}
}


impl<A> IntoIoSignature for [A;1] where A: Send + 'static{
    type InSig = InCol<A>;
    type OutSig = OutCol<A>;
    
    fn into_in_collection() -> Self::InSig{
	Default::default()
    }

    fn into_out_collection() -> Self::OutSig {
	OutCol::default()
    }

    fn send(self, executor: Arc<Executor>, out_signature: &Self::OutSig) -> Result<(), DErr>{
	let [a] = self;
	if let Some(e) = &out_signature.edge{
	    let edge_clone = e.clone();
	    let ec = executor.clone();
	    if let Err(e) = executor.schedule(Task::new(move||{
		if let Err(e) = edge_clone.send(ec, Box::new(a)){
		    error!("Failed to send data to next nodes: {:?}!", e);
		}
	    })){
		return Err(DErr::ExecutorError(e));
	    }
	}

	Ok(())
    }
    
    fn from_collection(collection: &mut Self::InSig) -> Self{
	[collection.value.take().unwrap()]
    }

    fn get_type_id(idx: usize) -> Option<TypeId> {
	if idx == 0{
	    Some(TypeId::of::<A>())
	}else{
	    None
	}
    }
}

///Implemets the IntoIoSignature trait for any tupel of the for (A, B, C, ...) denoted as impl_io!(A:0, B:1, C:2, ...);
#[macro_export]
macro_rules! impl_io {
    ($($Gen:ident : $Idx:tt), +) => {
	impl<$($Gen),+> IntoIoSignature for ($($Gen),+) where $($Gen : Send + 'static),+{
	    type InSig = ($(InCol<$Gen>),+);
	    type OutSig = ($(OutCol<$Gen>),+);

	    fn into_in_collection() -> Self::InSig{
		($(InCol::<$Gen>::default()),+)
	    }

	    fn into_out_collection() -> Self::OutSig{
		($(OutCol::<$Gen>::default()),+)
	    }

	    fn send(self, executor: Arc<Executor>, out_signature: &Self::OutSig) -> Result<(), DErr>{
		#[allow(non_snake_case)]
		let ($($Gen),+) = self;

		$(
		    if let Some(edge) = &out_signature.$Idx.edge{
			let edge_clone = edge.clone();
			let ec = executor.clone();
			if let Err(e) = executor.schedule(Task::new(move||{
			    if let Err(e) = edge_clone.send(ec, Box::new($Gen)){
				error!("Failed to send data to next node: port={}, type={} err={:?}", $Idx, stringify!($Gen), e);
			    }
			})){
			    return Err(DErr::ExecutorError(e));
			}
		    }
		)+
		Ok(())
	    }

	    fn from_collection(collection: &mut Self::InSig) -> Self{
		($(collection.$Idx.value.take().unwrap()),+)
	    }

	    fn get_type_id(idx: usize) -> Option<TypeId>{
		match idx{
		    $(
			$Idx => Some(TypeId::of::<$Gen>()),
		    )+
		    _ => None
		}
	    }
	}
    };
}


impl_io!(A:0, B:1);
impl_io!(A:0, B:1, C:2);
impl_io!(A:0, B:1, C:2, D:3);
impl_io!(A:0, B:1, C:2, D:3, E:4);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5, G:6);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9);
impl_io!(A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10);
impl_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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_io!(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);