Derive Macro derive_adhoc::Adhoc

source ·
#[derive(Adhoc)]
{
    // Attributes available to this derive:
    #[adhoc]
    #[derive_adhoc]
}
Expand description

Perform ad-hoc templating driven by a data structure

This macro does two things:

  1. It captures the data structure definition, so that it can be used with calls to derive_adhoc!.

  2. If #[derive_adhoc(MyMacro)] attributes are also specified, they are taken to refer to reuseable templates defined with define_derive_adhoc!. Each such MyMacro is applied to the data structure.

    You can specify expansion options for each such template application, by writing #[derive_adhoc(MyMacro[OPTIONS,..])], where [OPTIONS,..] is a comma-separated list of expansion options contained within [ ].

§#[adhoc] attribute

The contents of #[adhoc] attributes are made available to templates via the ${Xmeta} expansions.

If the template(s) don’t use them, they are ignored. derive-adhoc does not impose any namespacing within #[adhoc]: all templates see the same adhoc meta attributes.

§Captured data structure definition derive_adhoc_driver_TYPE

The data structure is captured by defining a macro_rules macro called derive_adhoc_driver_TYPE, where TYPE is the name of the type that #[derive(Adhoc)] is applied to.

§Scoping and ordering within the same crate

Summary of required ordering

  1. define_derive_adhoc! { MyMacro = ... }
  2. #[derive(Adhoc)] #[derive_adhoc(MyMacro)] struct MyStruct { ... }
  3. derive_adhoc! { MyStruct: ... }

Any reusable templates defined with define_derive_adhoc! must lexically their precede uses with #[derive(Adhoc) #[derive_adhoc(...)].

And, for one-off templates (derive_adhoc!), the data structure with its #[derive(Adhoc)] must lexically precede the references in derive_adhoc!, so that the data structure definition macro is in scope.

In each case, if the definition is in another module in the same crate, the defining module’s mod statement must come before the reference, and the mod statement will need #[macro_use]. So the placement and order of mod statements can matter.

§Applying a template (derive-adhoc macro) from another crate

#[derive_adhoc(some_crate::MyMacro)] applies an exported (pub) template defined and exported by some_crate.

You can import a template from another crate, so you can apply it with an unqualified name, with use, but the use must refer to the actual pattern macro name derive_adhoc_template_MyMacro:

use other_crate::derive_adhoc_template_TheirMacro;
#[derive(Adhoc)]
#[derive_Adhoc(TheirMacro)]
struct MyStruct { // ...

§Exporting the driver for downstream crates’ templates

To cause the macro embodying the driver struct to be exported, write: #[derive_adhoc(pub)]. The driver can then be derived from in other crates, with derive_adhoc! { exporting_crate::DriverStruct: ... }.

This is a tricky feature, which should only be used by experts who fully understand the implications. It effectively turns the body of the struct into a macro, with a brittle API and very limited support for namespacing or hygiene.

See pub mod a_driver in the example file pub-a.rs, in the source tree, for a fuller discussion of the implications, and some advice.

If you do this, you must pin your derive-adhoc to a minor version, as you may need to treat minor version updates in derive-adhoc as semver breaks for your crate.