Rust派生宏库derive-ex的使用,简化代码生成与自动化实现
Rust派生宏库derive-ex的使用,简化代码生成与自动化实现
derive-ex是一个改进版的宏库,用于实现标准库中定义的trait。它提供了比标准派生宏更智能的特性。
与标准派生宏的区别
- 自动生成的trait bound更智能
- 可以手动指定trait bound
- 可以为每个字段指定默认值
- 可以为每个字段指定比较方法
- 可以指定在派生
Debug
时忽略的字段 - 支持派生
Clone::clone_from
- 支持派生运算符(
Add
、AddAssign
、Not
、Deref
等)
支持的trait
Copy
Clone
Debug
Default
Ord
,PartialOrd
,Eq
,PartialEq
,Hash
- 运算符:
- Add-like (
Add
,Sub
,Mul
,Shl
等) - AddAssign-like (
AddAssign
,SubAssign
,MulAssign
,ShlAssign
等) - Not-like (
Not
,Neg
) Deref
,DerefMut
- Add-like (
不支持的trait
以下trait不支持,因为有更合适的crate可用:
trait | crate |
---|---|
Display , FromStr |
parse-display |
Error |
thiserror |
安装
在Cargo.toml中添加:
[dependencies]
derive-ex = "0.1.7"
示例
use derive_ex::derive_ex;
#[derive(Eq, PartialEq, Debug)]
#[derive_ex(Add, AddAssign, Clone, Default)]
struct X {
#[default(10)]
a: u32,
}
assert_eq!(X { a: 1 } + X { a: 2 }, X { a: 3 });
assert_eq!(X::default(), X { a: 10 });
#[derive(Eq, PartialEq, Debug)]
#[derive_ex(Clone, Default)]
enum Y {
A,
#[default]
B,
}
assert_eq!(Y::default(), Y::B);
完整示例
use derive_ex::derive_ex;
// 定义一个结构体,自动实现多个trait
#[derive(Debug)]
#[derive_ex(Clone, Default, Add, AddAssign, PartialEq)]
struct Point {
#[default(0.0)] // 设置默认值为0.0
x: f64,
#[default(0.0)]
y: f64,
}
// 定义一个枚举,自动实现Default和Clone
#[derive(Debug)]
#[derive_ex(Clone, Default)]
enum Shape {
#[default]
Circle,
Square,
Triangle,
}
fn main() {
// 测试结构体的Default实现
let p1 = Point::default();
println!("Default point: {:?}", p1); // Point { x: 0.0, y: 0.0 }
// 测试结构体的Add实现
let p2 = Point { x: 1.0, y: 2.0 };
let p3 = Point { x: 3.0, y: 4.0 };
let sum = p2 + p3;
println!("Sum of points: {:?}", sum); // Point { x: 4.0, y: 6.0 }
// 测试AddAssign
let mut p4 = Point { x: 1.0, y: 1.0 };
p4 += Point { x: 2.0, y: 2.0 };
println!("After +=: {:?}", p4); // Point { x: 3.0, y: 3.0 }
// 测试枚举的Default实现
let default_shape = Shape::default();
println!("Default shape: {:?}", default_shape); // Circle
// 测试Clone实现
let cloned_shape = default_shape.clone();
println!("Cloned shape: {:?}", cloned_shape); // Circle
}
许可证
本项目采用Apache-2.0/MIT双重许可。
贡献
除非您明确声明,否则您有意提交以包含在本工作中的任何贡献,如Apache-2.0许可证中所定义,应如上所述双重许可,没有任何附加条款或条件。
1 回复
以下是基于您提供的内容整理的Rust派生宏库derive-ex的完整示例演示:
内容中提供的示例
- 基本使用
use derive_ex::derive_ex;
#[derive_ex(Debug, Clone, PartialEq)]
struct Point {
x: i32,
y: i32,
}
- 自定义派生行为
#[derive_ex(Debug, Clone)]
struct User {
id: u64,
#[debug(skip)] // 在Debug输出中跳过password字段
password: String,
#[clone(skip)] // 克隆时跳过session_token字段
session_token: String,
}
- 为枚举自动派生
#[derive_ex(Debug, Clone, PartialEq)]
enum Status {
Active,
Inactive,
Suspended(String),
}
- 实现自定义trait
trait Greet {
fn greet(&self) -> String;
}
#[derive_ex(Greet)]
struct Person {
name: String,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("Hello, {}!", self.name)
}
}
- 高级示例:组合多个派生
#[derive_ex(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] // 与serde属性配合使用
struct ApiResponse<T> {
status_code: u16,
message: String,
data: T,
#[debug(with = "format_timestamp")]
#[serde(skip_serializing_if = "Option::is_none")]
timestamp: Option<u64>,
}
完整示例demo
// 完整示例:用户管理系统中的DTO和领域模型
use serde::{Serialize, Deserialize};
use derive_ex::derive_ex;
// 1. 定义自定义trait
trait DisplayName {
fn display_name(&self) -> String;
}
// 2. 用户DTO(数据传输对象)
#[derive_ex(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct UserDTO {
user_id: u64,
#[debug(skip)]
#[serde(skip_serializing)] // 不序列化密码
password: String,
username: String,
#[debug(with = "format_timestamp")]
created_at: u64,
}
// 3. 用户领域模型
#[derive_ex(Debug, Clone, DisplayName)]
struct User {
id: u64,
#[debug(skip)]
credentials: Credentials,
profile: Profile,
}
#[derive(Debug, Clone)]
struct Credentials {
hashed_password: String,
}
#[derive_ex(Debug, Clone, Serialize, Deserialize)]
struct Profile {
username: String,
email: String,
}
// 4. 实现自定义trait
impl DisplayName for User {
fn display_name(&self) -> String {
format!("{} ({})", self.profile.username, self.id)
}
}
// 5. 状态枚举
#[derive_ex(Debug, Clone, PartialEq, Serialize, Deserialize)]
enum AccountStatus {
Active,
Inactive {
reason: String,
since: u64,
},
#[serde(rename = "banned")]
Banned {
#[debug(skip)]
admin_notes: String,
until: Option<u64>,
},
}
// 辅助函数
fn format_timestamp(timestamp: &u64) -> String {
format!("{}", *timestamp) // 实际应用中可转换为可读日期
}
fn main() {
// 使用示例
let user_dto = UserDTO {
user_id: 123,
password: "secret".to_string(),
username: "john_doe".to_string(),
created_at: 1672531200,
};
let user = User {
id: 123,
credentials: Credentials {
hashed_password: "hashed_secret".to_string(),
},
profile: Profile {
username: "john_doe".to_string(),
email: "john@example.com".to_string(),
},
};
println!("User DTO: {:?}", user_dto);
println!("User display name: {}", user.display_name());
}
这个完整示例展示了:
- 自定义trait的自动实现
- DTO和领域模型的不同派生配置
- 枚举类型的复杂派生
- 与serde库的配合使用
- 字段级别的自定义行为控制
使用时需要确保Cargo.toml中包含以下依赖:
[dependencies]
derive-ex = "0.1"
serde = { version = "1.0", features = ["derive"] }