Rust宏扩展库amplify_derive的使用:简化代码生成与过程宏开发的强大工具
Rust宏扩展库amplify_derive的使用:简化代码生成与过程宏开发的强大工具
概述
Amplify库增强了Rust语言能力:提供多重泛型特性实现、类型包装器和派生宏。这是Rust语言放大库的一部分,提供了所需的派生宏。
最低支持的Rust编译器版本(MSRV):1.60.0。Rust 2021版。
主要功能
Display派生宏
- 使用其他格式化特性生成
Display
描述:
#[derive(Display, Debug)]
#[display(Debug)]
struct Some { /* ... */ }
- 使用现有函数显示描述:
#[derive(Display)]
#[display(Int::print)]
union Int { uint: u32, int: i32 };
impl Int {
pub fn print(&self) -> String {
s!("Integer representation")
}
}
- 自定义格式字符串:
#[derive(Display)]
#[display("({x}, {y})")]
struct Point { x: u32, y: u32 }
- 使用文档注释作为描述表示:
#[macro_use] extern crate amplify;
#[derive(Display)]
#[display(doc_comments)]
enum Variants {
/// Letter A
A,
/// Letter B
B,
/// This comment is ignored
#[display("Letter C")]
C,
/// Letter {_0}
Letter(String)
};
assert_eq!(format!("{}", Variants::C), "Letter C");
assert_eq!(format!("{}", Variants::Letter(s!("K"))), " Letter K");
Error派生宏
与Display
和From
派生宏配合使用效果最佳:
#[derive(Debug, Display, Error)]
#[display(doc_comments)]
enum Error {
/// I/O operation error
Io,
/// Math overflow
Overflow,
/// Zero division with {_0}
ZeroDivision(u16),
}
From派生宏
为整个实体或其单独字段实现From
特性:
#[derive(From, Default)]
#[from(::std::io::Error)]
pub struct IoErrorUnit;
#[derive(From, Default)]
#[from(::std::io::Error)]
pub struct IoError {
details: String,
#[from]
kind: IoErrorUnit,
}
#[derive(From)]
pub enum Error {
#[from(::std::io::Error)]
#[from(IoError)]
Io,
#[from]
Format(::std::fmt::Error),
#[from]
WithFields { details: ::std::str::Utf8Error },
MultipleFields {
#[from(IoErrorUnit)]
io: IoError,
details: String,
},
}
Wrapper派生宏
创建Rust新类型包装现有类型:
use std::marker::PhantomData;
use amplify::Wrapper;
#[derive(Clone, Wrapper, Default, From, Debug)]
struct Wrapped<T, U>(
#[wrap]
#[from]
HashMap<usize, Vec<U>>,
PhantomData<T>,
)
where
U: Sized + Clone;
let w = Wrapped::<(), u8>::default();
assert_eq!(w.into_inner(), HashMap::<usize, Vec<u8>>::default());
Getters派生宏
为结构体中的所有字段创建匹配字段名的getter方法:
#[derive(Getters, Default)]
struct One {
a: Vec<u8>,
pub b: bool,
pub(self) c: u8,
}
let one = One::default();
assert_eq!(one.a(), &Vec::<u8>::default());
assert_eq!(one.b(), &bool::default());
assert_eq!(one.c(), &u8::default());
AsAny派生宏
实现amplify::AsAny
特性,允许将任何类型转换为泛型"厚"指针&dyn Any
:
#[derive(AsAny, Copy, Clone, PartialEq, Eq, Debug)]
struct Point {
pub x: u64,
pub y: u64,
}
let mut point = Point { x: 1, y: 2 };
let point_ptr = point.as_any();
assert_eq!(point_ptr.downcast_ref(), Some(&point));
完整示例
以下是一个综合使用多个派生宏的完整示例:
use amplify::{AsAny, Wrapper};
use std::collections::HashMap;
use std::fmt;
// 使用Display派生宏
#[derive(Debug, Display)]
#[display(Debug)]
struct Some {
value: String,
}
// 使用Error派生宏
#[derive(Debug, Display, Error)]
#[display(doc_comments)]
enum AppError {
/// Invalid input provided
InvalidInput,
/// Operation failed with code {0}
OperationFailed(u32),
}
// 使用Wrapper派生宏
#[derive(Wrapper, Default, Debug)]
struct Count(#[wrap] u32);
// 使用Getters派生宏
#[derive(Getters)]
struct User {
name: String,
age: u8,
}
// 使用AsAny派生宏
#[derive(AsAny)]
struct AnyData {
content: String,
}
fn main() {
// Display示例
let s = Some { value: "test".to_string() };
println!("Display: {}", s);
// Error示例
let err = AppError::OperationFailed(404);
println!("Error: {}", err);
// Wrapper示例
let mut count = Count::default();
*count += 1;
println!("Count: {}", count.into_inner());
// Getters示例
let user = User { name: "Alice".to_string(), age: 30 };
println!("User: {}, {}", user.name(), user.age());
// AsAny示例
let data = AnyData { content: "secret".to_string() };
let any_ref = data.as_any();
if let Some(d) = any_ref.downcast_ref::<AnyData>() {
println!("Data content: {}", d.content);
}
}
安装
在项目目录中运行以下Cargo命令:
cargo add amplify_derive
或在Cargo.toml中添加:
amplify_derive = "4.0.1"
Amplify_derive是一个强大的Rust宏扩展库,可以显著简化代码生成和过程宏开发,特别适合需要大量样板代码的项目。
1 回复
Rust宏扩展库amplify_derive
使用指南
介绍
amplify_derive
是一个强大的Rust过程宏库,旨在简化代码生成和过程宏开发。它提供了一系列派生宏和实用工具,可以帮助开发者减少样板代码,提高开发效率。
主要特性
- 简化常见派生模式的实现
- 提供更友好的过程宏开发体验
- 支持自定义属性扩展
- 减少重复代码
安装
在Cargo.toml
中添加依赖:
[dependencies]
amplify_derive = "0.11"
使用方法
1. Display
派生宏
use amplify_derive::Display;
#[derive(Display)]
enum Error {
#[display("invalid argument: {0}")]
InvalidArgument(String),
#[display("I/O error occurred")]
IoError,
}
fn main() {
let err = Error::InvalidArgument("test".to_string());
println!("{}", err); // 输出: invalid argument: test
}
2. From
派生宏
use amplify_derive::From;
#[derive(From)]
enum Value {
Int(i32),
Float(f64),
String(String),
}
fn main() {
let int_val: Value = 42.into();
let str_val: Value = "hello".to_string().into();
}
3. Error
派生宏
use amplify_derive::{Display, Error};
use std::fmt;
#[derive(Debug, Display, Error)]
#[display(doc_comments)]
/// This is a custom error type
/// with multiple lines of documentation
struct CustomError;
fn main() {
let err = CustomError;
println!("{}", err); // 输出: This is a custom error type with multiple lines of documentation
}
4. 自定义属性
use amplify_derive::Wrapper;
#[derive(Wrapper)]
#[wrapper(Deref, Borrow, Display, From)]
struct Name(String);
fn main() {
let name = Name::from("Alice");
println!("{}", name); // 自动实现Display
let s: &str = &name; // 自动实现Deref到&str
}
5. 过程宏开发辅助
amplify_derive
还提供了一些实用工具来简化过程宏开发:
use amplify_derive::{Attr, ParseAttributes};
use syn::parse_macro_input;
#[derive(ParseAttributes)]
struct MyAttributes {
#[attr(optional)]
name: Option<String>,
#[attr(default = 42)]
count: u32,
}
// 在过程宏中使用
#[proc_macro_derive(MyDerive, attributes(my_attr))]
pub fn my_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let attrs = MyAttributes::parse(&input.attrs).unwrap();
// 使用解析出的属性生成代码
// ...
}
高级用法
组合使用多个派生宏
use amplify_derive::{Display, Error, From};
#[derive(Debug, Display, Error, From)]
enum ApiError {
#[display("Network error: {0}")]
Network(String),
#[display("Parse error")]
Parse,
#[from]
Io(std::io::Error),
}
fn main() -> Result<(), ApiError> {
let _file = std::fs::File::open("nonexistent.txt")?; // 自动转换为ApiError
Ok(())
}
自定义显示格式
use amplify_derive::Display;
#[derive(Display)]
#[display(inner)]
struct WrappedString(String);
fn main() {
let wrapped = WrappedString("hello".to_string());
println!("{}", wrapped); // 输出: hello
}
完整示例
下面是一个结合多个amplify_derive
功能的完整示例:
use amplify_derive::{Display, Error, From, Wrapper};
use std::fmt;
// 自定义错误类型
#[derive(Debug, Display, Error, From)]
enum AppError {
#[display("Configuration error: {0}")]
Config(String),
#[display("Database error")]
DbError,
#[from]
Io(std::io::Error),
}
// 包装器类型
#[derive(Wrapper, Display)]
#[wrapper(Deref, Display, From)]
#[display(inner)]
struct UserName(String);
// 主函数
fn main() -> Result<(), AppError> {
// 使用From派生宏
let name = UserName::from("JohnDoe");
println!("User: {}", name); // 输出: JohnDoe
// 使用Error派生宏
let _file = std::fs::File::open("missing.txt")?; // 自动转换为AppError
// 自定义错误
let err = AppError::Config("invalid setting".to_string());
println!("Error: {}", err); // 输出: Configuration error: invalid setting
Ok(())
}
总结
amplify_derive
通过提供一系列精心设计的派生宏和开发工具,显著简化了Rust中的代码生成和过程宏开发工作。无论是实现常见的trait还是开发自定义的过程宏,它都能帮助开发者减少样板代码,专注于业务逻辑的实现。