feat: enable generic access to message full names#27111
Conversation
yordis
commented
Apr 27, 2026
- Generic Rust code needs a stable way to refer to protobuf message full names without relying on unstable descriptor or reflection APIs.
- Message full names are known at code generation time, so exposing them as compile-time metadata avoids adding runtime lookup costs or kernel-specific reflection behavior.
- Keeping the API narrow and metadata-specific makes the new surface easier to reason about while covering both direct and generic Rust use cases.
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
|
LOCI found performance insights on your pull request. |
|
Thanks for raising this proposal! Definitely we want this or something like it: I just need to follow up on some details internally to see the shape that we might prefer before pulling the trigger. Just for some related info here, we've already cut our Q2 release (v35) and its intended to be the 'Rust API is intended no-more-breaking-changes; its the final release where gRPC or similar scope of user may ask for a final edge case breaking changes. v36 is our Q3 release and will drop the dash from our cratesio release numbers. Since we already cut v35-rc1 and from there only do patches to fix breakages, this shape of change will only ship v36 and so we have a little bit of time to decide while still ensuring it will go out at the same time it would otherwise anyway. |
|
Hey @esrauchg happy to see you again! I am around to do the work, so I will wait for your direction! |
- Event-sourced systems identify each event on the wire by its fully-qualified type name (e.g. `user.UserCreated`). To use a `buffa`-generated message directly as a domain event. Skipping the usual hand-written mapping layer between "domain type" and "storage type". Callers need that name as a compile-time constant on the type itself. Today it isn't there: the closest surface, `ExtensionSet::PROTO_FQN`, is bundled with the extension machinery and only emitted when a message opts into `unknown_fields=true`, which adds a hidden `__buffa_unknown_fields` field to the struct and forces every struct-literal construction in domain code to trail `..Default::default()`. Reaching for `buffa::ExtensionSet` just to read the FQN therefore drags in storage and ergonomic costs the caller doesn't want. - Following the same shape as [protocolbuffers/protobuf#27111](protocolbuffers/protobuf#27111), this PR introduces `buffa::MessageFullName` as a standalone trait with a single `const FULL_NAME: &'static str` item. Kept out of `Message` precisely so the FQN concern stays orthogonal and adding it doesn't break any hand-written `impl Message` in downstream code. Generic call sites import the trait (`use buffa::MessageFullName;`) and read `T::FULL_NAME` at compile time with no runtime indirection, so event stores, type registries, and `Any` type-URL construction can dispatch on it instead of maintaining a hand-written match arm per message. - `ExtensionSet::PROTO_FQN` is intentionally left in place to keep this change additive; the two consts are emitted from the same `proto_fqn` source in codegen so they cannot drift, and that invariant is documented at both sites. - The name `MessageFullName` / `FULL_NAME` mirrors the convention used across the protobuf ecosystem (and matches [protocolbuffers/protobuf#27111](protocolbuffers/protobuf#27111) to keep the two PRs aligned). Not attached to it. Happy to rename if a different spelling reads better here. Related: [TrogonStack/trogonai#108](TrogonStack/trogonai#108). --------- Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com> Co-authored-by: Iain McGinniss <309153+iainmcgin@users.noreply.github.com>