2022-06-27, 16:00–17:00 (UTC), Team 8
We will build a facility to allow easily autogenerating code from struct definitions in Rust: a facility combining the power of derive
, with the ease of use, especially in ad hoc cases, of macro_rules
.
Background
Rust has two primary macro systems: macro_rules
, which is easy to use, and proc macros, which are powerful: in particular, they can derive
: autogenerate code from data structure definitions.
Project goal and outline
This project will provide a facility which can be used to easily autogenerate code, ad-hoc, based on data structures, without having to write proc macro code (which is hard, and unsuitable for one-off use cases) and without having to try to write macro_rules pattern matchers for (sort-of-) struct definitions.
The project proposer has a plan for how to achieve this.
There are motivating use cases in the Arti code base, such as:
-
The channel operational parameters
struct is wrapped up in a macro call
so that a parameters update struct, and support code,
can be automatically generated. -
Where Arti's configuration contains lists of things,
we use macros to generate the types and accessors,
but the arrangements require us to
recapitulate the struct field definitions.
Skills and resources
Collaborators should have prior experience of Rust and a Rust development environment.
We will be writing proc macro code, but you can learn that on the job :-).
Indeed, this might be a fun opportunity to play with proc macros.
Example of what using this facility might look like:
#[derive(Adhoc)]
pub struct Config {
enabled: bool,
padding: PaddingParameters,
}
#[derive_adhoc(ChannelsParams)]
pub struct ChannelsParamsUpdates {
$(
pub(crate) $field: Option<$ty>,
)*
}
Implementation approach
1. #[derive(Adhoc)]
proc macro for saving struct definitions
When applied to the struct Config
, generates this:
macro_rules! derive_adhoc_apply_Config {
{ $($template:tt)* } => {
derive_adhoc_expand!{
{ pub struct Config { /* original struct definition */ } }
$($template)*
}
}
}
2. #[derive_adhoc]
attribute macro for applying to a template
When applied in the example above, generates this:
derive_adhoc_apply_ChannelsParams!{
pub struct ChannelsParamsUpdates { $( /* etc. */ )* }
}
3. function-like proc macro to do the actual expansion
The result of expanding the above is this:
derive_adhoc_expand!{
{ pub struct Config { /* original struct definition */ } }
pub struct ChannelsParamsUpdates { $( /* etc. */ )* }
}
derive_adhoc_expand
parses pub struct Config
,
and implements a bespoke template expander,
whose template syntax resembles the expansion syntax from macro_rules
.
Collaborators should have prior experience of Rust and a Rust development environment.
We will be writing proc macro code, but you can learn that on the job :-).
Indeed, this might be a fun opportunity to play with proc macros.
Ian (@Diziet) has been writing and publishing Free Software since 1989, and has been heavily involved in Debian, Xen, and now Arti (the Tor Project's Rust rewrite).
Ian's most recent big personal project is the Otter online board game system, also written (mostly) in Rust.