Automation of Destructure Pattern
destructure is an automation library for destructure pattern.
What is destructure pattern?
A structure with too many fields makes it hard to call constructors, but it is also hard work to prepare a Getter/Setter for each one. There are macros for this purpose, but even so, a large number of macros reduces readability. This is especially true when using From<T> Trait.
So how can this be simplified? It is the technique of "converting all fields to public".
This allows for a simplified representation, as in the following example
pub struct AuthenticateResponse {
id: Uuid,
user_code: String,
verification_uri: String,
expires_in: i32,
message: String,
}
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,
}
#[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);
}
There are several problems with this method, the most serious of which is the increase in boilerplate.
Using the multi-cursor feature of the editor, this can be done by copy-pasting, but it is still a hassle.
Therefore, I created a Procedural Macro that automatically generates structures and methods:
use destructure::Destructure;
#[derive(Destructure)]
pub struct AuthenticateResponse {
id: Uuid,
user_code: String,
verification_uri: String,
expires_in: i32,
message: String,
}
#[tokio::main]
async fn main() {
let res = reqwest::get("http://example.com")
.send().await.unwrap()
.json::<AuthenticateResponse>().await.unwrap();
let des: DestructAuthenticateResponse = res.into_destruct();
println!("{:?}", des.id);
}
You can also perform safe value substitution by using reconstruct() or substitute(),
which performs the same role as the following usage.
use destructure::{Destructure, Mutation};
#[derive(Destructure, Mutation)]
pub struct AuthenticateResponse {
id: Uuid,
user_code: String,
verification_uri: String,
expires_in: i32,
message: String,
}
#[tokio::main]
async fn main() {
let res = reqwest::get("http://example.com")
.send().await.unwrap()
.json::<AuthenticateResponse>().await.unwrap();
let message = "After".to_string();
let res: AuthenticateResponse = res.reconstruct(|before| {
before.message = message;
});
let mut res = res;
res.substitute(|before| {
*before.message = message;
});
println!("{:?}", des.id);
}
Problem
It is still lacking in functionality, but we will accept PullRequests and Issues if there are any problems.