10个版本 (4个重大更新)

0.5.6 2024年1月20日
0.5.5 2023年12月5日
0.4.5 2023年12月4日
0.3.0 2023年10月24日
0.1.2 2023年1月16日

#852过程宏


用于 rikka-mq

MIT/Apache

18KB
177

解构模式自动化

crate.io docs.rs

destructure 是一个针对 destructure pattern 的自动化库。

什么是 destructure pattern

具有太多字段的结构难以调用构造函数,但为每个字段准备 Getter/Setter 也很费时。为此存在宏,但即使是大量宏也会降低可读性。这在使用 From<T> 特性时尤为明显。

那么如何简化这一点呢?这就是“将所有字段转换为公共字段”的技术。

这允许进行简化表示,如下例所示

pub struct AuthenticateResponse {
    id: Uuid,
    user_code: String,
    verification_uri: String,
    expires_in: i32,
    message: String,
    // ... too many fields...
}

impl AuthenticateResponse {
    pub fn into_destruct(self) -> DestructAuthenticateResponse {
        DestructAuthenticateResponse {
            id: self.id,
            user_code: self.user_code,
            verification_uri: self.verification_uri,
            expires_in: self.expires_in,
            message: self.message,
            // ...
        }
    }
}

pub struct DestructAuthenticateResponse {
    pub id: Uuid,
    pub user_code: String,
    pub verification_uri: String,
    pub expires_in: i32,
    pub message: String,
    // ... too many fields (All `public`.)...
}

#[tokio::main]
async fn main() {
    let res = reqwest::get("http://example.com")
        .send().await.unwrap()
        .json::<AuthenticateResponse>().await.unwrap();
    
    let des = res.into_destruct();

    println!("{:?}", des.id);
}

这种方法有几个问题,其中最严重的是样板代码的增加。
使用编辑器的多光标功能,可以通过复制粘贴来完成,但这仍然很麻烦。

因此,我创建了一个 过程宏,可以自动生成结构和方法

use destructure::Destructure;

#[derive(Destructure)]
pub struct AuthenticateResponse {
    id: Uuid,
    user_code: String,
    verification_uri: String,
    expires_in: i32,
    message: String,
    // ... too many fields...
}

#[tokio::main]
async fn main() {
    let res = reqwest::get("http://example.com")
        .send().await.unwrap()
        .json::<AuthenticateResponse>().await.unwrap();

    // Auto generate
    let des: DestructAuthenticateResponse = res.into_destruct();

    println!("{:?}", des.id);
}

您还可以通过使用 reconstruct()substitute() 来执行安全值替换,
它们与以下用法具有相同的功能。

use destructure::{Destructure, Mutation};

#[derive(Destructure, Mutation)]
pub struct AuthenticateResponse {
    id: Uuid,
    user_code: String,
    verification_uri: String,
    expires_in: i32,
    message: String,
    // ... too many fields...
}

#[tokio::main]
async fn main() {
    let res = reqwest::get("http://example.com")
        .send().await.unwrap()
        .json::<AuthenticateResponse>().await.unwrap();

    let message = "After".to_string();
    
    // `reconstruct()` consumes self and provides the Destructed structure 
    // as a variable reference in a closure. 
    // Literally, it is a method that reconstructs.
    let res: AuthenticateResponse = res.reconstruct(|before| {
        before.message = message;
    });
    
    // substitute is a method that refills variable references of its own field values 
    // into another structure and provides them in a closure.
    //
    // This method is suitable for loop processing, etc., 
    // because it processes by reference as opposed to reconstruct, which consumes values.
    let mut res = res;
    res.substitute(|before| {
        *before.message = message;
    });

    println!("{:?}", des.id);
}

问题

功能仍然有限,但如果出现任何问题,我们将接受PullRequests和Issues。

依赖项

~320–780KB
~19K SLoC