#[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:
-
If
#[derive_deftly(MyMacro)]
attributes are also specified, they are taken to refer to reuseable templates defined withdefine_derive_deftly!
. Each suchMyMacro
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[ ]
. -
If
#[derive_deftly_adhoc]
is specified, captures the data structure definition, so that it can be used with calls toderive_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]
:
§Scoping and ordering within the same crate
Summary of required ordering
define_derive_deftly! { MyMacro = ... }
#[derive(Deftly)] #[derive_deftly(MyMacro)] struct MyStruct { ... }
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.
Alternatively, it is possible to use path-based scoping;
there is
an example in the Guide.
§Applying a template (derive-deftly macro) from another crate
#[derive_deftly(some_crate::MyMacro)]
applies an exported 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;
use other_crate::derive_deftly_template_TheirMacro;
#[derive(Deftly)]
#[derive_deftly(TheirMacro)]
struct MyStruct { // ...
§Captured data structure definition derive_deftly_driver_TYPE
With #[derive_deftly_adhoc]
,
the data structure is captured
for use by
derive_deftly_adhoc!
.
Specifically, 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.
§Exporting the driver for downstream crates’ templates
To cause the macro embodying the driver struct to be exported,
write:
#[derive_deftly_adhoc(export)]
.
The driver can then be derived from in other crates,
with derive_deftly_adhoc! { exporting_crate::DriverStruct: ... }
.
§Semver hazards
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.