mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-20 19:48:24 -07:00
127 lines
3.7 KiB
Rust
127 lines
3.7 KiB
Rust
//! Rust tree structure generation.
|
|
|
|
use std::collections::BTreeSet;
|
|
use std::fmt::Write;
|
|
|
|
use brk_types::TreeNode;
|
|
|
|
use crate::{
|
|
ClientMetadata, GenericSyntax, LanguageSyntax, PatternField, RustSyntax, build_child_path,
|
|
escape_rust_keyword, generate_leaf_field, generate_tree_node_field, prepare_tree_node,
|
|
to_snake_case,
|
|
};
|
|
|
|
/// Generate tree structs.
|
|
pub fn generate_tree(output: &mut String, catalog: &TreeNode, metadata: &ClientMetadata) {
|
|
writeln!(output, "// Series tree\n").unwrap();
|
|
|
|
let pattern_lookup = metadata.pattern_lookup();
|
|
let mut generated = BTreeSet::new();
|
|
generate_tree_node(
|
|
output,
|
|
"SeriesTree",
|
|
"",
|
|
catalog,
|
|
pattern_lookup,
|
|
metadata,
|
|
&mut generated,
|
|
);
|
|
}
|
|
|
|
fn generate_tree_node(
|
|
output: &mut String,
|
|
name: &str,
|
|
path: &str,
|
|
node: &TreeNode,
|
|
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
|
|
metadata: &ClientMetadata,
|
|
generated: &mut BTreeSet<String>,
|
|
) {
|
|
let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else {
|
|
return;
|
|
};
|
|
|
|
// Generate struct definition
|
|
writeln!(output, "/// Series tree node.").unwrap();
|
|
writeln!(output, "pub struct {} {{", name).unwrap();
|
|
|
|
for child in &ctx.children {
|
|
let field_name = escape_rust_keyword(&to_snake_case(child.name));
|
|
let type_annotation = if child.should_inline {
|
|
child.inline_type_name.clone()
|
|
} else {
|
|
metadata.field_type_annotation(&child.field, false, None, GenericSyntax::RUST)
|
|
};
|
|
writeln!(output, " pub {}: {},", field_name, type_annotation).unwrap();
|
|
}
|
|
|
|
writeln!(output, "}}\n").unwrap();
|
|
|
|
// Generate impl block
|
|
writeln!(output, "impl {} {{", name).unwrap();
|
|
writeln!(
|
|
output,
|
|
" pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {{"
|
|
)
|
|
.unwrap();
|
|
writeln!(output, " Self {{").unwrap();
|
|
|
|
let syntax = RustSyntax;
|
|
for child in &ctx.children {
|
|
let field_name = escape_rust_keyword(&to_snake_case(child.name));
|
|
|
|
if child.is_leaf {
|
|
if let TreeNode::Leaf(leaf) = child.node {
|
|
generate_leaf_field(
|
|
output,
|
|
&syntax,
|
|
"client.clone()",
|
|
child.name,
|
|
leaf,
|
|
metadata,
|
|
" ",
|
|
);
|
|
}
|
|
} else if child.should_inline {
|
|
// Inline struct type - only for nodes that don't match any pattern
|
|
let path_expr = syntax.path_expr("base_path", &format!("_{}", child.name));
|
|
writeln!(
|
|
output,
|
|
" {}: {}::new(client.clone(), {}),",
|
|
field_name, child.inline_type_name, path_expr
|
|
)
|
|
.unwrap();
|
|
} else {
|
|
generate_tree_node_field(
|
|
output,
|
|
&syntax,
|
|
&child.field,
|
|
metadata,
|
|
" ",
|
|
"client.clone()",
|
|
&child.base_result,
|
|
);
|
|
}
|
|
}
|
|
|
|
writeln!(output, " }}").unwrap();
|
|
writeln!(output, " }}").unwrap();
|
|
writeln!(output, "}}\n").unwrap();
|
|
|
|
// Generate child structs
|
|
for child in &ctx.children {
|
|
if child.should_inline {
|
|
let child_path = build_child_path(path, child.name);
|
|
generate_tree_node(
|
|
output,
|
|
&child.inline_type_name,
|
|
&child_path,
|
|
child.node,
|
|
pattern_lookup,
|
|
metadata,
|
|
generated,
|
|
);
|
|
}
|
|
}
|
|
}
|