Rust宏编程库cairo-lang-macro的使用,Cairo语言宏扩展与代码生成工具
Cairo Lang Macro
这个crate为Cairo语言提供了编写Scarb procedural宏的API。
安装
在项目目录中运行以下Cargo命令:
cargo add cairo-lang-macro
或者在Cargo.toml中添加以下行:
cairo-lang-macro = "0.2.0"
示例使用
以下是一个使用cairo-lang-macro创建自定义derive宏的完整示例:
use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
// Parse the input tokens into a syntax tree
let input = parse_macro_input!(input as DeriveInput);
// Get the name of the struct/enum we're deriving for
let name = input.ident;
// Build the output, possibly using quote! macro
let output = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("Hello, Macro! My name is {}!", stringify!(#name));
}
}
};
// Return the generated code as TokenStream
TokenStream::from(output)
}
更复杂的示例
这是一个更复杂的示例,展示了如何使用cairo-lang-macro创建属性宏:
use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};
#[proc_mature_attribute]
pub fn log_execution_time(_attr: TokenStream, item: TokenStream) -> TokenStream {
// Parse the input function
let input_fn = parse_macro_input!(item as ItemFn);
// Get function details
let fn_name = &input_fn.sig.ident;
let fn_block = &input_fn.block;
// Generate the output with timing logic
let output = quote! {
fn #fn_name() {
use std::time::Instant;
let start = Instant::now();
#fn_block
let duration = start.elapsed();
println!("Function {} took {:?}", stringify!(#fn_name), duration);
}
};
TokenStream::from(output)
}
完整示例
下面是一个完整的项目示例,展示如何使用cairo-lang-macro:
- 首先创建一个新的库项目:
cargo new --lib cairo_macro_example
cd cairo_macro_example
- 添加依赖到Cargo.toml:
[lib]
proc-macro = true
[dependencies]
cairo-lang-macro = "0.2.0"
syn = { version = "2.0", features = ["full"] }
quote = "1.0"
- 在src/lib.rs中实现自定义宏:
use cairo_lang_macro::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
// 自定义derive宏实现
#[proc_macro_derive(VersionInfo)]
pub fn version_info_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let output = quote! {
impl VersionInfo for #name {
fn version() -> &'static str {
env!("CARGO_PKG_VERSION")
}
fn author() -> &'static str {
env!("CARGO_PKG_AUTHORS")
}
}
};
TokenStream::from(output)
}
// 属性宏实现
#[proc_macro_attribute]
pub fn debug_log(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input_fn = parse_macro_input!(item as ItemFn);
let fn_name = &input_fn.sig.ident;
let fn_block = &input_fn.block;
let output = quote! {
fn #fn_name() {
println!("[DEBUG] Entering function: {}", stringify!(#fn_name));
#fn_block
println!("[DEBUG] Exiting function: {}", stringify!(#fn_name));
}
};
TokenStream::from(output)
}
- 在另一个项目中使用这些宏:
use cairo_macro_example::{VersionInfo, debug_log};
#[derive(VersionInfo)]
struct MyStruct;
#[debug_log]
fn my_function() {
println!("Doing some work...");
}
fn main() {
println!("MyStruct version: {}", MyStruct::version());
println!("MyStruct author: {}", MyStruct::author());
my_function();
}
使用场景
cairo-lang-macro特别适用于:
- 为Cairo语言创建自定义derive宏
- 开发代码生成工具
- 实现领域特定语言(DSL)
- 创建编译时验证和转换
版本信息
当前版本:v0.2.0
最小支持Rust版本:v1.73.0
许可证:MIT
1 回复
以下是关于cairo-lang-macro的完整示例demo,基于您提供的内容:
1. 简单宏完整示例
use cairo_lang_macro::proc_macro;
use proc_macro::TokenStream;
/// 一个简单的宏,将输入原样返回
#[proc_macro]
pub fn identity_macro(input: TokenStream) -> TokenStream {
// 直接返回输入不做任何处理
input
}
// 使用示例:
// let result = identity_macro!(println!("Hello"));
2. 属性宏完整示例
use cairo_lang_macro::proc_macro_attribute;
use proc_macro::TokenStream;
/// 属性宏示例,添加函数调用日志
#[proc_macro_attribute]
pub fn log_function(attr: TokenStream, item: TokenStream) -> TokenStream {
// 解析输入函数
let mut input_fn: syn::ItemFn = syn::parse(item).unwrap();
// 获取函数名
let fn_name = &input_fn.sig.ident;
// 在函数体开头插入日志语句
let new_stmt: syn::Stmt = syn::parse_quote! {
println!("调用函数: {}", stringify!(#fn_name));
};
input_fn.block.stmts.insert(0, new_stmt);
// 返回修改后的TokenStream
TokenStream::from(quote::quote! { #input_fn })
}
// 使用示例:
// #[log_function]
// fn my_function() {
// println!("执行中...");
// }
3. 派生宏完整示例
use cairo_lang_macro::{proc_macro_derive, parse_macro_input, DeriveInput};
use proc_macro::TokenStream;
use quote::quote;
/// 派生宏示例,为结构体生成默认实现
#[proc_macro_derive(DefaultStruct)]
pub fn default_struct_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
// 生成默认实现
let expanded = quote! {
impl #name {
pub fn default() -> Self {
Self {
// 默认字段值
}
}
}
};
expanded.into()
}
// 使用示例:
// #[derive(DefaultStruct)]
// struct MyStruct {
// field1: u32,
// field2: String,
// }
4. 代码生成完整示例
use cairo_lang_macro::proc_macro;
use proc_macro::{TokenStream, Ident, Span};
use quote::quote;
/// 生成带有getter方法的简单结构体
#[proc_macro]
pub fn generate_getter_struct(input: TokenStream) -> TokenStream {
let struct_name = Ident::new("Person", Span::call_site());
let output = quote! {
struct #struct_name {
name: String,
age: u32,
}
impl #struct_name {
pub fn get_name(&self) -> &str {
&self.name
}
pub fn get_age(&self) -> u32 {
self.age
}
}
};
output.into()
}
// 使用示例:
// generate_getter_struct!();
5. 语法树操作完整示例
use cairo_lang_macro::{parse_macro_input, DeriveInput};
use proc_macro::TokenStream;
use quote::quote;
/// 为结构体生成builder模式实现
#[proc_macro_derive(Builder)]
pub fn builder_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident;
let builder_name = Ident::new(&format!("{}Builder", name), Span::call_site());
let expanded = quote! {
struct #builder_name {
inner: #name,
}
impl #builder_name {
fn new() -> Self {
Self {
inner: #name::default(),
}
}
fn build(self) -> #name {
self.inner
}
}
};
expanded.into()
}
// 使用示例:
// #[derive(Builder, Default)]
// struct User {
// id: u64,
// name: String,
// }