Rust宏扩展库amplify_derive的使用:简化代码生成与过程宏开发的强大工具

Rust宏扩展库amplify_derive的使用:简化代码生成与过程宏开发的强大工具

概述

Amplify库增强了Rust语言能力:提供多重泛型特性实现、类型包装器和派生宏。这是Rust语言放大库的一部分,提供了所需的派生宏。

最低支持的Rust编译器版本(MSRV):1.60.0。Rust 2021版。

主要功能

Display派生宏

  1. 使用其他格式化特性生成Display描述:
#[derive(Display, Debug)]
#[display(Debug)]
struct Some { /* ... */ }
  1. 使用现有函数显示描述:
#[derive(Display)]
#[display(Int::print)]
union Int { uint: u32, int: i32 };

impl Int {
    pub fn print(&self) -> String {
        s!("Integer representation")
    }
}
  1. 自定义格式字符串:
#[derive(Display)]
#[display("({x}, {y})")]
struct Point { x: u32, y: u32 }
  1. 使用文档注释作为描述表示:
#[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派生宏

DisplayFrom派生宏配合使用效果最佳:

#[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还是开发自定义的过程宏,它都能帮助开发者减少样板代码,专注于业务逻辑的实现。

回到顶部