Learning Rust: The derive attribute
When you have a lot of traits to implement for your types, it can quickly become tedious and may add a lot of complexity to your code.
struct Point {
x: u64,
y: u64,
}
impl Debug for Point {
// ...
}
impl Display for Point {
// ...
}
impl Something for Point {
// ...
}
impl SomethingElse for Point {
// ...
}
// ...
Fortunately, Rust has something for us: the derive
attribute.
By using the derive
attribute, we are actually feeding our types to a Derive macro which is a kind of procedural macro.
They take code as input (in this case, our type), and create more code as output. At compile-time.
This post is an excerpt from my book Black Hat Rust
This is especially useful for data deserialization: Just by implementing the Serialize
and Deserialize
traits from the serde
crate, the (almost) universally used serialization library in the Rust world, we can then serialize and deserialize our types to a lot of data formats: JSON, YAML, TOML, BSON and so on...
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Point {
x: u64,
y: u64,
}
Without much effort, we just implemented the Debug
, Clone
, Serialize
and Deserialize
traits for our struct Point
.
One thing to note is that all the subfields of your struct
need to implement the traits:
use serde::{Serialize, Deserialize};
// Not possible:
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Point<T> {
x: T,
y: T,
}
// instead, you need to do this:
use serde::{Serialize, Deserialize};
use core::fmt::Debug; // Import the Debug trait
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Point<T: Debug + Clone + Serialize + Deserialize> {
x: T,
y: T,
}
Want to learn more about Rust, applied Cryptography and Security? Take a look at my book Black Hat Rust.