A first example: derive_deftly(HelloWorld)

Here we'll make an example project with a simple derive-deftly template. Our template won't do much, but it will get us started using the system.

To begin with, we'll create a new project:

$ cargo init --lib dd-hello-world
$ cd dd-hello-world

Next, we'll add the derive-deftly crate as a new dependency:

Note: You could also add the dependency by adding a line like this to the [dependencies] section in your Cargo.toml:

derive-deftly = "0.10"

(You should replace 0.10 with the real latest version.)

Now we can edit src/lib.rs in our project to define and use a new template.

Writing our HelloWorld template

There are two parts to using derive-deftly: specifying templates that you can use to derive new features for your structs and enums and then applying those templates to your types.

To define a template, you use define_derive_deftly!, as in

#![allow(unused)]
fn main() {
use derive_deftly::define_derive_deftly;

define_derive_deftly! {
    HelloWorld:

    impl $ttype {
        pub fn greet() {
            println!("Greetings from {}", stringify!($ttype));
        }
    }
}
}

This is a very simple template: it uses a single expansion: $ttype. (We'll get into more expansions, and more useful examples, later on. For now, all you need to know is that $ttype expands to the type on which you're applying your template.)

Later on, you can apply HelloWorld to your own type with [#[derive(Deftly)]derive-Deftly, as in:

#![allow(unused)]
fn main() {
use derive_deftly::define_derive_deftly;
define_derive_deftly! {
   HelloWorld:

   impl $ttype {
       pub fn greet() {
           println!("Greetings from {}", stringify!($ttype));
       }
   }
}
use derive_deftly::Deftly;

#[derive(Clone, Debug, Deftly)]
#[derive_deftly(HelloWorld)]
pub struct MyStruct;

MyStruct::greet();
}

Limitations of our template

Our template won't work for every type! For example, suppose that we try to apply it to a generic type:

#[derive(Deftly)]
#[derive_deftly(HelloWorld)]
struct Pair<T> {
    first: T,
    second: T,
}

In response, derive-deftly will try to expand our template to something like this:

impl Pair {
    pub fn greet() {
        println!("Greetings from {}", stringify!(Pair));
    }
}

But that won't work in Rust. Instead, we would need a template to expand to something more like this:

impl<T> Pair<T> {
    ...
}

We'll talk about how to make templates work for types like this in later chapters.

What's next?

Next, we'll take a detour, and show how to expose our template so that it can be used in other modules, and other crates.

After that, we'll look over a more complex example, and learn more features of derive-deftly. We'll write a more useful template, and have it apply to more types.