
Ссылка на проект: https://github.com/saschagrunert/indextree/pull/110
Макрос, предназначенный для работы с библиотекой indextree, который принимает человечески читаемую структуру дерева и создает структуру дерева в памяти.
Реализация написана как процедурный макрос, так как я хотел минимизировать количество рекурсии и сохранить читаемость кода, учитывая его сложность.
Вот пример использования макроса, взятый прямо из его документации:
let root_node = arena.new_node("root node");
tree!(
&mut arena,
root_node => {
"1",
"2" => {
"2_1" => { "2_1_1" },
"2_2",
},
"3",
}
);
let automagical_root_node = tree!(
&mut arena,
"root node, but automagically created" => {
"1",
"2" => {
"2_1" => { "2_1_1" },
"2_2",
},
"3",
}
);Он принимает мутабельный референс на Arena, а затем принимает саму структуру дерева. Результатом вызова tree! является NodeId, указывающий на корень только что созданного узла. Ему также можно передать NodeId, и он будет строиться на основе уже существующего узла.
Для автоматического определения того, является ли предоставленный корневой узел NodeId или каким-то другим типом, я использовал autoref specialization, так как обычная специализация ещё не добавлена в Rust для общего использования.
Огромное спасибо сообществу Rust за то, что указали на дыры в безопасности памяти и рассказали про autoref specialization!