macro-data 0.1.0

Utitlies to transfer data between procedural macros
Documentation
#[cfg(feature = "proc-macro")]
mod proc_macro;

#[cfg(feature = "proc-macro")]
pub use proc_macro::*;

/// This macro is used by other proc macros to transfer data.
///
/// It must be public to use it, but please don't call it directly.
///
/// Internal
/// - The entry syntax is `macro_data_transfer!(<target-macro-path>, (<tokens>));`
/// - Keep the result in `accu`, which is a list of tokentrees
///     - Nested groups create a new tokentree to the left
///     - Closing the group combines two tokentrees
/// - Use `@load(<path>)` to call a macro and use the returned tokens
///     - Other tokens are returned as is
#[macro_export]
macro_rules! macro_data_transfer {
    // open ()
    (
        @normal,
        $target:path,
        ($accu:tt, $($accu_tail:tt,)*),
        (($($arg:tt)*) $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            ((), $accu, $($accu_tail,)*),
            ($($arg)* @close_param $($arg_tail)*),
        );
    };

    // close ()
    (
        @normal,
        $target:path,
        (($($accu:tt)*), ($($accu_prev:tt)*), $($accu_tail:tt,)*),
        (@close_param $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            (($($accu_prev)* ($($accu)*)), $($accu_tail,)*),
            ($($arg_tail)*),
        );
    };

    // open []
    (
        @normal,
        $target:path,
        ($accu:tt, $($accu_tail:tt,)*),
        ([$($arg:tt)*] $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            ((), $accu, $($accu_tail,)*),
            ($($arg)* @close_bracket $($arg_tail)*),
        );
    };

    // close []
    (
        @normal,
        $target:path,
        (($($accu:tt)*), ($($accu_prev:tt)*), $($accu_tail:tt,)*),
        (@close_bracket $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            (($($accu_prev)* [$($accu)*]), $($accu_tail,)*),
            ($($arg_tail)*),
        );
    };

    // open {}
    (
        @normal,
        $target:path,
        ($accu:tt, $($accu_tail:tt,)*),
        ({$($arg:tt)*} $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            ((), $accu, $($accu_tail,)*),
            ($($arg)* @close_braces $($arg_tail)*),
        );
    };

    // close []
    (
        @normal,
        $target:path,
        (($($accu:tt)*), ($($accu_prev:tt)*), $($accu_tail:tt,)*),
        (@close_braces $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            (($($accu_prev)* {$($accu)*}), $($accu_tail,)*),
            ($($arg_tail)*),
        );
    };

    // load data start
    (
        @normal,
        $target:path,
        $accu:tt,
        (@load ($data:path) $($arg_tail:tt)*),
    ) => {
        $data!(
            $crate::macro_data_transfer,
            (
                @ret,
                $target,
                $accu,
                ($($arg_tail)*),
            ),
        );
    };

    // load data return
    (
        (
            @ret,
            $target:path,
            (($($accu:tt)*), $($accu_tail:tt,)*),
            $arg_tail:tt,
        ),
        ($($value:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            (($($accu)* $($value)*), $($accu_tail,)*),
            $arg_tail,
        );
    };

    // any arg
    (
        @normal,
        $target:path,
        (($($accu:tt)*), $($accu_tail:tt,)*),
        ($arg:tt $($arg_tail:tt)*),
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            (($($accu)* $arg), $($accu_tail,)*),
            ($($arg_tail)*),
        );
    };

    // all parsed
    (
        @normal,
        $target:path,
        ($accu:tt,),
        (),
    ) => {
        $target! $accu;
    };

    // public call
    (
        $target:path,
        $arg:tt,
    ) => {
        $crate::macro_data_transfer!(
            @normal,
            $target,
            ((),),
            $arg,
        );
    };
}