Skip to content

Commit b241d9f

Browse files
committed
c19: A custom derive macro that automatically implements a trait on a struct
1 parent a054c3f commit b241d9f

File tree

7 files changed

+103
-0
lines changed

7 files changed

+103
-0
lines changed

c19_macro/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
workspace = { members = ["hello_macro", "pancakes"] }

c19_macro/hello_macro/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#workspace = { members = ["hello_macro_derive"] }
2+
[package]
3+
name = "hello_macro"
4+
version = "0.1.0"
5+
edition = "2021"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "hello_macro_derive"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
9+
[lib]
10+
proc-macro = true
11+
12+
[dependencies]
13+
syn = "1.0"
14+
quote = "1.0"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use proc_macro::TokenStream;
2+
use quote::quote;
3+
use syn;
4+
5+
#[proc_macro_derive(HelloMacro)]
6+
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
7+
// Construct a representation of Rust code as a syntax tree
8+
// that we can manipulate
9+
let ast = syn::parse(input).unwrap();
10+
// Build the trait implementation
11+
12+
impl_hello_macro(&ast)
13+
}
14+
15+
fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
16+
let name = &ast.ident;
17+
let gen = quote!{
18+
impl HelloMacroTrait for #name {
19+
fn hello_macro() {
20+
println!("Hello, Macro! My name is {}!", stringify!(#name));
21+
}
22+
}
23+
};
24+
gen.into()
25+
}
26+
27+
#[cfg(test)]
28+
mod tests {
29+
use super::*;
30+
31+
#[test]
32+
fn hello_macro_derive_works() {
33+
//let result = add(2, 2);
34+
//assert_eq!(result, 4);
35+
}
36+
}

c19_macro/hello_macro/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pub trait HelloMacroTrait {
2+
fn hello_macro();
3+
}
4+
5+
pub fn add(left: usize, right: usize) -> usize {
6+
left + right
7+
}
8+
9+
#[cfg(test)]
10+
mod tests {
11+
use super::*;
12+
13+
#[test]
14+
fn hello_macro_test() {
15+
let result = add(2, 2);
16+
assert_eq!(result, 4);
17+
}
18+
}

c19_macro/pancakes/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "pancakes"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
hello_macro = {path = "../hello_macro"}
10+
hello_macro_derive = {path = "../hello_macro/hello_macro_derive"}

c19_macro/pancakes/src/main.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use hello_macro::HelloMacroTrait;
2+
use hello_macro_derive::HelloMacro;
3+
4+
5+
#[derive(HelloMacro)]
6+
struct Pancakes;
7+
8+
9+
#[derive(HelloMacro)]
10+
struct Icecakes;
11+
fn main() {
12+
println!("HelloMacro is a custom derivable macro that automatically implements trait HelloMacroTrait on a struct.");
13+
Pancakes::hello_macro();
14+
Icecakes::hello_macro();
15+
}

0 commit comments

Comments
 (0)