Skip to content

buffa-build: path-scoped preserve_unknown_fields_in for per-message unknown-field preservation #281

Description

@iainmcgin

Motivation

preserve_unknown_fields(bool) is currently all-or-nothing. Disabling it is a legitimate memory optimization (drops the UnknownFields Vec header from every message), but it also silently removes round-trip fidelity everywhere — including on the handful of message types that actually get re-encoded, forwarded, or persisted. #269 is a concrete case: a client disabled preservation globally for memory and then lost unknown closed-enum values on forwarding paths.

A path-scoped variant lets a build keep the memory savings globally while retaining wire fidelity on the specific types that need it:

buffa_build::Config::new()
    .preserve_unknown_fields(false)                       // global default
    .preserve_unknown_fields_in(&[".wa.CallLogRecord",    // per-message overrides
                                  ".wa.SyncdMutation"])

Shape

  • Follows the existing _in convention (bytes_type_in, string_type_in, unbox_oneof_in): proto-path prefixes resolved through matches_proto_prefix, global default first, last matching rule wins.
  • Granularity is per-message. The flag gates whether the message struct carries __buffa_unknown_fields: UnknownFields at all, so rules match message FQNs and package prefixes. Per-field granularity is not representable in the storage model.
  • Nested/child messages resolve independently: a preserved outer message retains only its own-level unknown fields; each nested type is governed by its own matching rule.

Implementation notes

The global bool is consulted in several places today — struct field emission (message.rs), the decode arms (including the closed-enum unknown route), encode, the view decoders, and the JSON/extension-range interaction. The change is mechanical: resolve the flag per message from (global, rules) instead of reading one bool, and thread that resolution through the existing call sites.

Priority

Low. The default configuration already preserves unknown fields everywhere; this only benefits builds that opt out for memory and want selective fidelity back. For the #269 use case specifically, a scoped closed-enum openness override (discussed on that issue) is the more direct fix; this option is complementary.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions