Derive Macro tor_hsservice::internal_prelude::Deftly

#[derive(Deftly)]
{
    // Attributes available to this derive:
    #[deftly]
    #[derive_deftly]
    #[derive_deftly_adhoc]
}
Expand description

Perform ad-hoc templating driven by a data structure

This macro does two things:

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

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

  2. If #[derive_deftly_adhoc] is specified, captures the data structure definition, so that it can be used with calls to derive_deftly_adhoc!.

§#[deftly] attribute

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

If none of the template(s) recognise them, it is an error, (unless #[derive_deftly_adhoc] is specified).

derive-deftly does not impose any namespacing within #[deftly]:

§Captured data structure definition derive_deftly_driver_TYPE

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

§Scoping and ordering within the same crate

Summary of required ordering

  1. define_derive_deftly! { MyMacro = ... }
  2. #[derive(Deftly)] #[derive_deftly(MyMacro)] struct MyStruct { ... }
  3. derive_deftly_adhoc! { MyStruct: ... }

Any reusable templates defined with define_derive_deftly! must lexically their precede uses with #[derive(Deftly) #[derive_deftly(...)].

And, for one-off templates (derive_deftly_adhoc!), the data structure with its #[derive(Deftly)] must lexically precede the references in derive_deftly_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-deftly macro) from another crate

#[derive_deftly(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_deftly_template_MyMacro:

use derive_deftly::{Deftly, derive_deftly_adhoc};
use other_crate::derive_deftly_template_TheirMacro;
#[derive(Deftly)]
#[derive_deftly(TheirMacro)]
struct MyStruct { // ...

§Exporting the driver for downstream crates’ templates

To cause the macro embodying the driver struct to be exported, write: #[derive_deftly_adhoc(pub)]. The driver can then be derived from in other crates, with derive_deftly_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-deftly to a minor version, as you may need to treat minor version updates in derive-deftly as semver breaks for your crate. And every time you update, you must read the CHANGELOG.md, since there is nothing that will warn you automatically about breaking changes.