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
}
}
}
#[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);