#[macro_export]
macro_rules! impl_typesystem {
(
system = $TS:tt,
mappings = {
$(
{ $($V:tt)|+ => $NT:ty }
)*
}
) => {
impl $crate::connectorx::typesystem::TypeSystem for $TS {}
$(
impl_typesystem!(@typeassoc $TS [$($V)+], $NT);
)+
impl_typesystem!(@realize $TS $([ [$($V)+] => $NT ])+ );
};
(@typeassoc $TS:tt [$($V:tt)+], $NT:ty) => {
impl<'r> $crate::connectorx::typesystem::TypeAssoc<$TS> for $NT {
fn check(ts: $TS) -> $crate::connectorx::errors::Result<()> {
match ts {
$(
$TS::$V(false) => Ok(()),
)+
_ => fehler::throw!($crate::connectorx::errors::ConnectorXError::TypeCheckFailed(format!("{:?}", ts), std::any::type_name::<$NT>()))
}
}
}
impl<'r> $crate::connectorx::typesystem::TypeAssoc<$TS> for Option<$NT> {
fn check(ts: $TS) -> $crate::connectorx::errors::Result<()> {
match ts {
$(
$TS::$V(true) => Ok(()),
)+
_ => fehler::throw!($crate::connectorx::errors::ConnectorXError::TypeCheckFailed(format!("{:?}", ts), std::any::type_name::<$NT>()))
}
}
}
};
(@realize $TS:tt $([ [$($V:tt)+] => $NT:ty ])+) => {
impl<'r, F> $crate::connectorx::typesystem::Realize<F> for $TS
where
F: $crate::connectorx::typesystem::ParameterizedFunc,
$(F: $crate::connectorx::typesystem::ParameterizedOn<$NT>,)+
$(F: $crate::connectorx::typesystem::ParameterizedOn<Option<$NT>>,)+
{
fn realize(self) -> $crate::connectorx::errors::Result<F::Function> {
match self {
$(
$(
$TS::$V(false) => Ok(F::realize::<$NT>()),
)+
$(
$TS::$V(true) => Ok(F::realize::<Option<$NT>>()),
)+
)+
}
}
}
};
}
#[macro_export]
macro_rules! impl_transport {
(
name = $TP:ty,
error = $ET:ty,
systems = $TSS:tt => $TSD:tt,
route = $S:ty => $D:ty,
mappings = {
$(
{ $($TOKENS:tt)+ }
)*
}
) => {
$(
impl_transport!(@cvt $TP, $($TOKENS)+);
)*
impl_transport!(@transport $TP, $ET [$TSS, $TSD] [$S, $D] $([ $($TOKENS)+ ])*);
};
(@transport $TP:ty, $ET:ty [$TSS:tt, $TSD:tt] [$S:ty, $D:ty] $([ $($TOKENS:tt)+ ])*) => {
impl <'tp> $crate::connectorx::typesystem::Transport for $TP {
type TSS = $TSS;
type TSD = $TSD;
type S = $S;
type D = $D;
type Error = $ET;
impl_transport!(@cvtts [$TSS, $TSD] $([ $($TOKENS)+ ])*);
impl_transport!(@process [$TSS, $TSD] $([ $($TOKENS)+ ])*);
impl_transport!(@processor [$TSS, $TSD] $([ $($TOKENS)+ ])*, $([ $($TOKENS)+ ])*);
}
};
(@cvtts [$TSS:tt, $TSD:tt] $( [$V1:tt [$T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident] )*) => {
fn convert_typesystem(ts: Self::TSS) -> $crate::connectorx::errors::Result<Self::TSD> {
match ts {
$(
$TSS::$V1(true) => Ok($TSD::$V2(true)),
$TSS::$V1(false) => Ok($TSD::$V2(false)),
)*
#[allow(unreachable_patterns)]
_ => fehler::throw!($crate::connectorx::errors::ConnectorXError::NoConversionRule(
format!("{:?}", ts), format!("{}", std::any::type_name::<Self::TSD>())
))
}
}
};
(@process [$TSS:tt, $TSD:tt] $([ $V1:tt [$T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident ])*) => {
fn process<'s, 'd, 'r>(
ts1: Self::TSS,
ts2: Self::TSD,
src: &'r mut <<Self::S as $crate::connectorx::sources::Source>::Partition as $crate::connectorx::sources::SourcePartition>::Parser<'s>,
dst: &'r mut <Self::D as $crate::connectorx::destinations::Destination>::Partition<'d>,
) -> Result<(), Self::Error> where Self: 'd {
match (ts1, ts2) {
$(
($TSS::$V1(true), $TSD::$V2(true)) => {
let val: Option<$T1> = $crate::connectorx::sources::PartitionParser::parse(src)?;
let val: Option<$T2> = <Self as TypeConversion<Option<$T1>, _>>::convert(val);
$crate::connectorx::destinations::DestinationPartition::write(dst, val)?;
Ok(())
}
($TSS::$V1(false), $TSD::$V2(false)) => {
let val: $T1 = $crate::connectorx::sources::PartitionParser::parse(src)?;
let val: $T2 = <Self as TypeConversion<$T1, _>>::convert(val);
$crate::connectorx::destinations::DestinationPartition::write(dst, val)?;
Ok(())
}
)*
#[allow(unreachable_patterns)]
_ => fehler::throw!($crate::connectorx::errors::ConnectorXError::NoConversionRule(
format!("{:?}", ts1), format!("{:?}", ts1))
)
}
}
};
(@processor [$TSS:tt, $TSD:tt] $([ $V1:tt [$T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident ])*, $([ $($TOKENS:tt)+ ])*) => {
fn processor<'s, 'd>(
ts1: Self::TSS,
ts2: Self::TSD,
) -> $crate::connectorx::errors::Result<
fn(
src: &mut <<Self::S as $crate::connectorx::sources::Source>::Partition as $crate::connectorx::sources::SourcePartition>::Parser<'s>,
dst: &mut <Self::D as $crate::connectorx::destinations::Destination>::Partition<'d>,
) -> Result<(), Self::Error>
> where Self: 'd {
match (ts1, ts2) {
$(
($TSS::$V1(true), $TSD::$V2(true)) => {
impl_transport!(@process_func_branch true [ $($TOKENS)+ ])
}
($TSS::$V1(false), $TSD::$V2(false)) => {
impl_transport!(@process_func_branch false [ $($TOKENS)+ ])
}
)*
#[allow(unreachable_patterns)]
_ => fehler::throw!($crate::connectorx::errors::ConnectorXError::NoConversionRule(
format!("{:?}", ts1), format!("{:?}", ts1))
)
}
}
};
(@process_func_branch $OPT:ident [ $V1:tt [&$L1:lifetime $T1:ty] => $V2:tt [&$L2:lifetime $T2:ty] | conversion $HOW:ident ]) => {
impl_transport!(@process_func_branch $OPT &$T1, &$T2)
};
(@process_func_branch $OPT:ident [ $V1:tt [$T1:ty] => $V2:tt [&$L2:lifetime $T2:ty] | conversion $HOW:ident ]) => {
impl_transport!(@process_func_branch $OPT $T1, &$T2)
};
(@process_func_branch $OPT:ident [ $V1:tt [&$L1:lifetime $T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident ]) => {
impl_transport!(@process_func_branch $OPT &$T1, $T2)
};
(@process_func_branch $OPT:ident [ $V1:tt [$T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident ]) => {
impl_transport!(@process_func_branch $OPT $T1, $T2)
};
(@process_func_branch true $T1:ty, $T2:ty) => {
Ok(
|s: &mut _, d: &mut _| $crate::connectorx::typesystem::process::<Option<$T1>, Option<$T2>, Self, Self::S, Self::D, <Self::S as $crate::connectorx::sources::Source>::Error, <Self::D as $crate::connectorx::destinations::Destination>::Error, Self::Error>(s, d)
)
};
(@process_func_branch false $T1:ty, $T2:ty) => {
Ok(
|s: &mut _, d: &mut _| $crate::connectorx::typesystem::process::<$T1, $T2, Self, Self::S, Self::D, <Self::S as $crate::connectorx::sources::Source>::Error, <Self::D as $crate::connectorx::destinations::Destination>::Error, Self::Error>(s, d)
)
};
(@cvt $TP:ty, $V1:tt [$T1:ty] => $V2:tt [$T2:ty] | conversion $HOW:ident) => {
impl_transport!(@cvt $HOW $TP, $T1, $T2);
};
(@cvt auto $TP:ty, $T1:ty, $T2:ty) => {
impl<'tp, 'r> $crate::connectorx::typesystem::TypeConversion<$T1, $T2> for $TP {
fn convert(val: $T1) -> $T2 {
val as _
}
}
impl_transport!(@cvt option $TP, $T1, $T2);
};
(@cvt auto_vec $TP:ty, $T1:ty, $T2:ty) => {
impl<'tp, 'r> $crate::connectorx::typesystem::TypeConversion<$T1, $T2> for $TP {
fn convert(val: $T1) -> $T2 {
val.into_iter().map(|v| v as _).collect()
}
}
impl_transport!(@cvt option $TP, $T1, $T2);
};
(@cvt owned $TP:ty, $T1:ty, $T2:ty) => {
impl<'tp, 'r> $crate::connectorx::typesystem::TypeConversion<$T1, $T2> for $TP {
fn convert(val: $T1) -> $T2 {
val.to_owned()
}
}
impl_transport!(@cvt option $TP, $T1, $T2);
};
(@cvt option $TP:ty, $T1:ty, $T2:ty) => {
impl<'tp, 'r> $crate::connectorx::typesystem::TypeConversion<Option<$T1>, Option<$T2>> for $TP {
fn convert(val: Option<$T1>) -> Option<$T2> {
val.map(Self::convert)
}
}
};
(@cvt none $TP:ty, $T1:ty, $T2:ty) => {};
}