macro-template 0.1.0-rc.1

Macro to generate repeated Rust code with table-driven sources.
Documentation

macro-template

Crates.io Documentation MSRV 1.85 Apache 2.0 licensed Build Status

Overview

macro-template is a procedural macro that generates repeated Rust code in multiple places with table-driven sources.

For example, the following code generates From implementations for MyEnum from all its variants:

enum MyEnum {
    A(MyStructA),
    B(MyStructB),
    C(MyStructC),
}

macro_template::template! {
    for (Variant, Type) in [(A, MyStructA), (B, MyStructB), (C, MyStructC)] {
        impl From<Type> for MyEnum {
            fn from(value: Type) -> Self {
                MyEnum::Variant(value)
            }
        }
    }
}

You can iterate over a matrix as well:

macro_template::template! {
    for (Endian, Method) in [
        (LittleEndian, to_le_bytes),
        (BigEndian, to_be_bytes),
        (NativeEndian, to_ne_bytes)
    ],
    for (Ty, Width) in [
        (u16, 2),
        (u32, 4),
    ],
    {
        impl StoreBytes<Endian, Width> for Ty {
            fn store_bytes(&self) -> [u8; Width] {
                self.Method()
            }
        }
    }
}

Or, you can generate repeated match arms by pattern:

macro_template::template! {
    for T in [Int, Real, Double] {
        match Foo {
            @splice { EvalType::T => { panic!("{}", EvalType::T); }, }
            EvalType::Other => unreachable!(),
        }
    }
}

Naturally, if the match arm differs left-hand side and right-hand side:

macro_template::template! {
    for (K, Value) in [
        (Apple, "apple"),
        (Banana, "banana"),
        (Cherry, "cherry"),
    ] {
        match kind {
            @splice { Kind::K => { println!("{}", Value); }, }
        }
    }
}

The iterator can be a sequence of numbers, characters, or bytes:

// sequential numeric counter
let tuple = (1000, 100, 10);
let mut sum = 0;
macro_template::template! {
    for i in [0..3] {
        sum += tuple.i;
    }
}
assert_eq!(sum, 1110);

// sequential character collector
let mut string = String::new();
macro_template::template! {
    for c in ['x'..='z'] {
        string.push(c);
    }
}
assert_eq!(string, "xyz");

You can combine multiple iterators in a single template:

let mut values = Vec::new();

macro_template::template! {
    for Prefix in ["read", "write"],
    for Code in 200..=201 {
        values.push((Prefix, Code));
    }
}

assert_eq!(
    values,
    [("read", 200), ("read", 201), ("write", 200), ("write", 201)],
);

Minimum Rust version policy

This crate's minimum supported rustc version is 1.85.0.

The current policy is that the minimum Rust version required to use this crate can be increased in minor version updates. For example, if crate 1.0 requires Rust 1.85.0, then crate 1.0.z for all values of z will also require Rust 1.85.0 or newer. However, crate 1.y for y > 0 may require a newer minimum version of Rust.

License

This project is licensed under Apache License, Version 2.0.

Origins