I want to implement declarative macro that will allow me to insert variables into proc macro attribute.
So, I have a struct like this:
#[derive(Packet, Debug)]
#[option(opcode=Opcode::SMSG_MESSAGECHAT)]
struct Test {
#[dynamic_field]
field1: u8,
#[dynamic_field]
field2: u16,
#[dynamic_field]
field3: u8,
#[dynamic_field]
field4: u8,
field5: String,
}
impl Test {
// ...
}
and I want to insert expression inside #[option(opcode=...)]
, but since there restrictions on proc macro side, I want to use declarative macros like next to bypass proc macro restrictions:
#[macro_export]
macro_rules! with_opcode {
(
$(opcode:$opcode:expr;)?
$(#[$outer:meta])*
$($PacketStruct: item)*
) => {
$(#[$outer])*
$(#[option(opcode=$opcode)])*
$($PacketStruct)*
};
}
this macros expected to be used like next:
with_opcode! {
opcode: Opcode::SMSG_MESSAGECHAT;
#[derive(Packet, Debug)]
struct Test {
#[dynamic_field]
field1: u8,
#[dynamic_field]
field2: u16,
#[dynamic_field]
field3: u8,
#[dynamic_field]
field4: u8,
field5: String,
}
impl Test {
// ...
}
}
but when I try this macros I got an error on compile:
error: local ambiguity when calling macro `with_opcode`: multiple parsing options: built-in NTs item ('PacketStruct') or 1 other option.
--> src\main.rs:9:5
|
9 | opcode: Opcode::SMSG_MESSAGECHAT;
| ^^^^^^
I also tried to use macros in different way:
#[macro_export]
macro_rules! with_opcode {
(
opcode: $opcode:expr;
$(#[$outer:meta])*
$($tt:tt)*
) => {
$(#[$outer])*
#[option(opcode=$opcode)]
with_opcode!($($tt)*);
};
(
$vis:vis struct $PacketStruct:ident {
$($field_vis:vis $field_name:ident: $field_type:ty),*$(,)?
}
$($PacketStructImpl: item)*
) => {
$vis struct $PacketStruct {
$($field_vis $field_name: $field_type),*
}
$($PacketStructImpl)*
};
}
but have same issue.
Could somebody explain how to fix this issue ? And if this have sense or declarative macros will not help me to bypass proc macro restrictions ?