pub trait Tx<D, R = ()> {
fn execute(self, data: &mut D) -> R;
}
#[macro_export]
macro_rules! NestedTx {
($visibility:vis $name:ident<$data:tt> {
$(
$variant:tt (
$(
$(#[$m:meta])*
$field_name:ident : $field_type:ty
),* $(,)?
) -> $return_type:ty = $tx_fn:expr
),* $(,)?
}) => {
#[derive(serde::Serialize, serde::Deserialize)]
$visibility enum $name {
$(
$variant($variant),
)*
}
impl $crate::Tx<$data> for $name {
fn execute(self, data: &mut $data) {
match self {
$(
$name::$variant(it) => {
it.execute(data);
}
)*
}
}
}
$(
$crate::Subtx! {
#[tx($name)]
$visibility struct $variant {
$(
$field_name: $field_type,
)*
}
impl $crate::Tx<$data, $return_type> for $variant {
fn execute(self, data: &mut $data) -> $return_type {
$tx_fn(data, self)
}
}
}
)*
};
}
#[macro_export]
macro_rules! Subtx {
(
#[tx($wrapper:tt)]
$visibility:vis struct $tx_struct:tt {
}
$tx_impl:item
) => {
#[derive(serde::Serialize, serde::Deserialize)]
$visibility struct $tx_struct;
$crate::EnumBorrowOwned!($wrapper, $tx_struct);
$tx_impl
};
(
#[tx($wrapper:tt)]
$visibility:vis struct $tx_struct:tt {
$($field_name:ident : $field_type:ty),* $(,)?
}
$tx_impl:item
) => {
#[derive(serde::Serialize, serde::Deserialize)]
$visibility struct $tx_struct {
$($field_name : $field_type),*
}
$crate::EnumBorrowOwned!($wrapper, $tx_struct);
$tx_impl
};
}
#[macro_export]
macro_rules! EnumBorrowOwned {
($wrapper:tt, $sub:tt) => {
$crate::EnumBorrowOwned!($wrapper::$sub, $sub);
};
($wrapper:tt :: $wrapper_variant:tt, $sub:tt) => {
impl Into<$wrapper> for $sub {
fn into(self) -> $wrapper {
$wrapper::$wrapper_variant(self)
}
}
impl From<$wrapper> for $sub {
fn from(value: $wrapper) -> Self {
match value {
$wrapper::$wrapper_variant(q) => q,
#[allow(unreachable_patterns)]
_ => unreachable!(),
}
}
}
};
}