You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add support for mapping old fields to new ones in TLV read macros
As we've grown, we regularly face a question of whether to "break
out" of our nice TLV-based struct/enum reading/writing macros in
order to handle mapping legacy fields to new ones, or deal with
keeping the legacy fields and handling at runtime what should be
hanlded at (de-)serialization time.
This attempts to address this tradeoff by adding support for a
"legacy" TLV read. This read style allows us to read a TLV which is
not directly mapped to any fields in the struct/enum but which can
be computed from the struct/enum's layout at write-time and which
is incorporated into the read data at read-time.
It takes a type, a `$read` expression (which is executed after all
TLVs are read but before the struct/enum is built) and a `$write`
expression (which is executed to calculate the value to write in
the TLV).
They are always read as `option`s to retain a future ability to
remove the `legacy` fields.
Sadly, there's two issues with doing this trivially which force us
into `proc-macro` land:
(a) when matching the original struct we want to list the fields
in the match arm so that we have them available to write.
Sadly, we can't call a macro to have it write out the field
name based on the field type, so instead need to pass the whole
match to a proc-macro and have it walk through to find the
types and skip fields that are `legacy`.
(b) when building a final struct/enum after reading, we need to
list a few `$field: $expr`s and cannot decide whether to
include a field based on a regular macro.
The proc-macros to do so aren't trivial, but they aren't that bad
either. We could instead try to rewrite our TLV stream processing
macros to handle a new set of TLVs which are passed via a separate
argument, but as TLVs are required to in ordered by type this
requires a good chunk of additional generated code in each TLV
write. It also would result in a somewhat less ergonomic callsite
as it would no longer fit into our existing list of TLVs.
0 commit comments