I have a structure with two optional fields and would like to provide special macro to simplify instances creation.
The macro have to accept one required argument and three optional arguments. Last optional argument have to accept list of values. And I would like to use exactly one patter for that.
Finally I did that and everything works fine:
#[derive(Debug)]
pub enum Variant {
OptionOne,
OptionTwo,
}
#[derive(Debug)]
pub struct TheStruct{
string: String,
first: Option<Variant>,
second: Option<Variant>,
numbers: Vec<u32>,
}
impl TheStruct {
// doesn't matter
}
#[doc(hidden)]
#[macro_export]
macro_rules! the_macro_int {
($the_struct:ident, numbers, { $($w:expr),*$(,)*}) => {
$($the_struct.numbers.push($w);)*
};
($the_struct:ident, first, {$w:expr}) => {
$the_struct.first = Some($w);
};
($the_struct:ident, second, {$w:expr}) => {
$the_struct.second = Some($w);
};
}
#[macro_export]
macro_rules! the_macro {
(string: $string:expr, $($kind:ident : $val:tt),*$(,)*) => {{
let mut the_struct = $crate::TheStruct{
string: $string,
first: None,
second: None,
numbers: std::vec::Vec::new(),
};
$($crate::the_macro_int!(the_struct, $kind, $val);)*
the_struct
}};
}
fn main() {
let the_struct = the_macro!(
string: "Hello".to_owned(),
first: { Variant::OptionOne },
numbers: (1, 3, 4),
);
println!("the_struct:{:?}", the_struct);
}
The one thing makes me unhappy: the brackets in first: { Variant::OptionOne },
.
I tried to replace my pattern by (string: $string:expr, $($kind:ident : $val:expr),*$(,)*)
but it doesn't work for numebrs
anymore.
Is it possible to redefine pattern for the_macro
to allow first: Variant::OptionOne,
to be a valid while numbers
still can accept a list of items? Kind of brackets for numbers
doesn't matter but I can't replace list of things with just Vec or something similar.
P.S. I don't looking for a solution with multiple patterns.