I'm trying to use a TT muncher to create a nested hash map structure. The basic type definition is
type Object = HashMap<String, Node>;
enum Node {
Terminal(String),
Nested(Object),
}
I know that I can manually create these objects:
let mut x: Object = HashMap::new();
x.insert("foo".into(), Node::Terminal("bar".into()));
x.insert("bing".into(), {
let mut bing = HashMap::new();
bing.insert("bar".into(), Node::Terminal("baz".into()));
Node::Nested(bing)
});
And this does generate the expected structure
{
"bing": Nested(
{
"bar": Terminal(
"baz"
)
}
),
"foo": Terminal(
"bar"
)
}
But I have a few large literals in this format, and I'd prefer to use a less ugly syntax, so I'm trying to make a macro. Here's a minimum example of what I think should work:
use std::collections::HashMap;
type Object = HashMap<String, Node>;
#[derive(Debug)]
enum Node {
Terminal(String),
Nested(Object),
}
macro_rules! obj {
{
$($tt:tt)*
} => {
{
let map = ::std::collections::HashMap::new();
obj!(@parse; map; ($($tt)*));
map
}
};
(@parse; $name:ident; ()) => {};
(@parse; $name:ident; ($key:expr => $value:expr, $($tail:tt)*)) => {
$name.insert($key.into(), Node::Terminal($value.into()));
obj!(@parse; $name; ($($tail)*));
};
(@parse; $name:ident; ($key:expr => $value:block, $($tail:tt)*)) => {
$name.insert($key.into(), Node::Nested(obj!{$value}));
obj!(@parse; $name; ($($tail)*));
};
}
fn main() {
let x: Object = obj!{
"foo" => "bar",
"bing" => {
"bar" => "baz",
},
};
println!("{:#?}", x);
}
This does not work, I get a recursion error when I try to compile it:
error: recursion limit reached while expanding the macro `obj`
--> src/main.rs:22:13
|
22 | obj!(@parse; map; ($($tt)*));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
40 | let x: Object = obj!{
| _____________________-
41 | | "foo" => "bar",
42 | | "bing" => {
43 | | "bar" => "baz",
44 | | },
45 | | };
| |_____- in this macro invocation
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
I've tried bumping the recursion limit way up, and it does not terminate. What am I missing in my macro?