2 个版本
0.0.1 | 2024年2月10日 |
---|---|
0.0.0 | 2023年12月8日 |
#4 in #hand-written
34KB
695 行
Codebiber
此包是一个用于元编程的 Rust 库。它允许将自动生成的代码混合到手写代码中。它深受 Ned Batchelder 的 cog 应用程序的启发。
免责声明
此作品按“原样”提供,不提供任何类型的保证或条件。
这是一个实验性库,具有实验性的 API、行为和实现,没有长期计划。自行承担风险。
变更日志
v0.0.1
- 最低支持的 Rust 版本是现在 1.63(对于常规构建,而不是开发构建) 05ed194ddaa2127b671c0345cfdf8e4330419242
- 不再使用不稳定的功能 0341b2d033173a4f7d6e084ae14bd36f623db9d5
lib.rs
:
示例
使用 codebiber 混合自动生成代码和手写代码的愚蠢示例。
在这里,原始代码包含手写行
void handwritten_line1();
void handwritten_line2();
void handwritten_line3();
void handwritten_line4();
void handwritten_line5();
和一些标记为要覆盖的部分
// << codegen foo >>
// << /codegen >>
// << codegen bar >>
// << /codegen >>
以及另一个函数已生成的部分
// << codegen baz >>
void generated_line_by_some_other_function();
// << /codegen >>
函数 generate
接受输入代码、一个 配置,最重要的是要生成的函数。
在我们的例子中,该函数将对每个部分调用一次。每次它接受部分名称(在我们的情况下 foo
、bar
或 baz
)并返回此部分的生成代码。如果部分不是其责任范围,它也可以返回 Ok(None) 并再次使用先前的内容。
在我们的例子中,生成函数 gen_code_lines
为 foo
和 bar
部分返回新的代码,而将 baz
保持不变。
这导致生成的代码部分
// << codegen foo >>
void autogen_line_foo();
// << /codegen aaa272 >>
// << codegen bar >>
void autogen_line_bar1();
void autogen_line_bar2();
// << /codegen 00a214 >>
// << codegen baz >>
void generated_line_by_some_other_function();
// << /codegen 810c07 >>
注意哈希值。它们可以防止意外修改的覆盖。它们只是 blake3 哈希的前几个字节(可以配置多少)。
extern crate codebiber;
const INPUT : &str = r"
void handwritten_line1();
void handwritten_line2();
// << codegen foo >>
// << /codegen >>
void handwritten_line3();
// << codegen bar >>
// << /codegen >>
void handwritten_line4();
// << codegen baz >>
void generated_line_by_some_other_function();
// << /codegen >>
void handwritten_line5();
";
fn main() -> codebiber::Result
{
let cfg = codebiber::Config{
// Anything checksum length other than 0 will catch unintended modifications
// since the last modification.
checksum_bytes_to_store: 3,
};
let actual_output = codebiber::generate(INPUT, cfg, gen_code_lines)?;
assert_eq!(actual_output, Some(EXPECTED_OUTPUT.to_owned()));
Ok(())
}
fn gen_code_lines(name: &str) -> codebiber::Fmt_Result
{
let generated = match name
{
"foo" => Some("void autogen_line_foo();".to_owned()),
"bar" => Some("void autogen_line_bar1();\nvoid autogen_line_bar2();".to_owned()),
_ => None,
};
Ok(generated)
}
const EXPECTED_OUTPUT : &str = r"
void handwritten_line1();
void handwritten_line2();
// << codegen foo >>
void autogen_line_foo();
// << /codegen aaa272 >>
void handwritten_line3();
// << codegen bar >>
void autogen_line_bar1();
void autogen_line_bar2();
// << /codegen 00a214 >>
void handwritten_line4();
// << codegen baz >>
void generated_line_by_some_other_function();
// << /codegen 810c07 >>
void handwritten_line5();
";
请注意,bar
部分中生成的代码缩进。这是因为生成的代码继承了标记行的缩进 // << codegen bar >>
示例 2
虽然在这个例子中所有标记行都从 //
开始,但标记行可以以任何字符开始,只要它们不以 <
结尾,并且不包含 <<
extern crate codebiber;
const INPUT : &str = r"
/* << codegen foo >>
依赖关系
~4.5MB
~99K SLoC