Description
When using derive
, it is often useful to be able to make common structs that contain fields where everything can be done automatically, and then surrounding structs where only some of the things are derived.
To do this, one needs to indicate to each derive macro that the fields of a contained struct should be imported without another level of nesting. #[serde(flatten)]
, #[row(flatten)]
. But unfortunately there is not a #[field(flatten)]
.
For example, I have this in a work-in-progress webapp:
#[derive(Debug,Serialize)]
struct PageContext {
#[serde(flatten)] frow: FlightRow,
hidden_vals: TemplateEnumRadio<IsHidden>,
}
#[derive(Debug,Serialize,FromSqlRow)]
struct FlightRow {
flight: Flight,
branch: String,
hidden: IsHidden,
webgroup: String,
main_tree: String,
template_flight: Option<Flight>,
basis_flight: Option<Flight>,
reuse_real_builds: bool,
xtrees_web: String,
xtrees_main: String,
job_patterns: String,
#[serde(flatten)] #[row(flatten)]
common: RowUpdateCommon,
}
#[derive(Debug,FromForm)]
struct UpdateForm {
common: RowUpdateCommon, // this wants to be flatten
}
#[derive(Debug,Serialize,FromForm,FromSqlRow)]
struct RowUpdateCommon {
email: String,
}
This doesn't work because the generated code expects form submissions containing common.email
but the actual form contains only email
.
Alternatives Considered
Letting the fields be nested the way FromForm
wants doesn't really work, because whether a field ends up in common
depends not on anything principled about the system, but simply on whether the automatic handling produced by the derive macros is appropriate.
For now I have to just give up on making this part of my code common, and writing some boilerplate to copy fields from one struct to another.
Additional Context
I'm not convinced that field
is a good name for this attribute. Derive macro inert attributes are in a global namespace. I suggest that form
would be better. However, it is perhaps too late to change this now.