Expand description
§Automation of Destructure Pattern
destructure
is an automation library for destructure pattern
.
§Usage
use destructure::Destructure;
#[derive(Destructure)]
pub struct Book {
id: u64,
name: String,
stocked_at: String,
author: String,
// ... too many fields...
}
fn main() {
let book = Book {
id: 1234_5678_9999_0000u64,
name: "name".to_string(),
stocked_at: "2023/01/03".to_string(),
author: "author".to_string()
};
// Auto generate
let des: DestructBook = book.into_destruct();
println!("{:?}", des.id);
}
§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 Book {
id: u64,
name: String,
stocked_at: String,
author: String,
// ... too many fields...
}
impl Book {
pub fn into_destruct(self) -> DestructBook {
DestructBook {
id: self.id,
name: self.name,
stocked_at: self.stocked_at,
author: self.author,
}
}
}
pub struct DestructBook {
pub id: u64,
pub name: String,
pub stocked_at: String,
pub author: String,
// ... too many fields (All `public`.)...
}
fn main() {
let book = Book {
id: 1234_5678_9999_0000u64,
name: "name".to_string(),
stocked_at: "2023/01/03".to_string(),
author: "author".to_string()
};
let des = book.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 Book {
id: u64,
name: String,
stocked_at: String,
author: String,
// ... too many fields...
}
fn main() {
let book = Book {
id: 1234_5678_9999_0000u64,
name: "name".to_string(),
stocked_at: "2023/01/03".to_string(),
author: "author".to_string()
};
// Auto generate
let des: DestructBook = book.into_destruct();
println!("{:?}", des.id);
}
You can also perform safe value substitution by using reconstruct()
,
which performs the same role as the following usage.
use destructure::Destructure;
#[derive(Debug, Eq, PartialEq, Clone, Destructure)]
pub struct Book {
id: u64,
name: String,
stocked_at: String,
author: String,
// ... too many fields...
}
fn main() {
let before = Book {
id: 1234_5678_9999_0000u64,
name: "name".to_string(),
stocked_at: "2023/01/03".to_string(),
author: "author".to_string()
};
let author = "After".to_string();
// Auto generate
let after = before.clone().reconstruct(|before| {
before.author = author;
});
assert_ne!(before, after);
}
Derive Macros§
- Destructure
- Automatically implements
into_destruct()
andfreeze()
methods. - Destructure
Ref - Automatically implements
as_destruct()
method. - Mutation
- Automatically implements
substitute()
methods.