How to create a macro that return tuple of different types of data?

How to create a macro that return tuple of different types of data?

What I am trying to achive

middleware! {
        ctx,
        true,
        ctx.response.body = "Mid 2".to_owned();
        let end = Instant::now();
        println!("Response Time: {:?}", end.duration_since(start));
        (c, true)
    }

The macro I wrote

macro_rules! middleware {
    ($context:expr, $next:expr, $func:ident) => {
        (
            $context,
            $next,
            Some(Box::new(move |mut $context| Box::pin(async move { $func }))),
        )
    };
}

Well, your third parameter is $func:ident, but

ctx.response.body = "Mid 2".to_owned();
let end = Instant::now();
println!("Response Time: {:?}", end.duration_since(start));
(c, true)

is definitely not an identifier. Indeed you cannot match that code snippet (a sequence of several statements) with any of the macro designators, as they're all meant to match a single "unit" of Rust code. The closest you can get is with either the block or tt designators, but these still require you to wrap the code in {} braces:

middleware! {
    ctx,
    true,
    { 
        ctx.response.body = "Mid 2".to_owned();
        let end = Instant::now();
        println!("Response Time: {:?}", end.duration_since(start));
        (c, true)
    }
}

I'd call that an improvement when it comes to readability.

Another problem is that you have |mut $context| in the macro body, but the $context metavariable is an expr rather than ident and thus cannot occur as the name of a closure parameter. Rust macros are "typed" in the sense that a metavariable's designator must match the syntactic position in which the metavariable is used.

3 Likes

Thank you so much
It is working now