I have a macros and I want to avoid code duplication there (first and third rules are pretty similar). Could somebody share common practices and good hints of how to do this ?
This is my macros:
#[macro_export]
macro_rules! packet {
// first rule
(
properties {
$(opcode $opcode_value:expr;)?
}
$(#[$outer:meta])*
$vis:vis struct $PacketStruct:ident {
$($field_name:ident: $field_type:ty),*$(,)?
}
$($PacketStructImpl: item)*
) => {
$(#[$outer])*
#[derive(Clone, PartialEq, Debug)]
$vis struct $PacketStruct {
$($field_name: $field_type),*
}
$($PacketStructImpl)*
$(
impl $PacketStruct {
pub fn get_opcode() -> u32 {
$opcode_value as u32
}
}
)?
impl $PacketStruct {
pub fn to_binary(&mut self) -> Vec<u8> {
let mut packet = Vec::new();
$(
$crate::types::traits::BinaryConverter::write_into(
&mut self.$field_name,
&mut packet
);
)*;
packet
}
}
};
// eof first rule
// second rule
(
properties {
opcode $opcode_value:expr;
$($prop_name:ident: $prop_type:ty;)*
}
$(#[$outer:meta])*
$vis:vis struct $PacketStruct:ident {
$($field_name:ident: $field_type:ty),*$(,)?
}
$($PacketStructImpl: item)*
) => {
packet! {
properties {
$($prop_name: $prop_type;)*
}
$(#[$outer])*
$vis struct $PacketStruct {
$($field_name: $field_type),*
}
$($PacketStructImpl)*
impl $PacketStruct {
pub fn get_opcode() -> u32 {
$opcode_value as u32
}
}
}
};
// eof of second rule
// third rule
(
properties {
$($prop_name:ident: $prop_type:ty;)*
}
$(#[$outer:meta])*
$vis:vis struct $PacketStruct:ident {
$($field_name:ident: $field_type:ty),*$(,)?
}
$($PacketStructImpl: item)*
) => {
$(#[$outer])*
#[derive(Clone, PartialEq, Debug)]
$vis struct $PacketStruct {
$($field_name: $field_type),*
}
$($PacketStructImpl)*
impl $PacketStruct {
pub fn to_binary(&mut self) -> Vec<u8> {
let mut packet = Vec::new();
$(
$crate::types::traits::BinaryConverter::write_into(
&mut self.$field_name,
&mut packet
);
)*;
packet
}
}
};
}
This is sandbox (with example of how to use it).