Skip to content

refactor: replace ProtoMeta AST inspection with prost::Name + prost-reflect - #538

Closed
vbarua wants to merge 8 commits into
mainfrom
vbarua/prost-reflect-experiment
Closed

refactor: replace ProtoMeta AST inspection with prost::Name + prost-reflect#538
vbarua wants to merge 8 commits into
mainfrom
vbarua/prost-reflect-experiment

Conversation

@vbarua

@vbarua vbarua commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the brittle compile-time AST inspection in the ProtoMeta derive macro with proper runtime protobuf introspection via prost::Name and prost-reflect.

  • Message type names: now come from prost::Name::full_name() (generated by prost_build::Config::enable_type_names()), replacing the cook_path(module_path!(), ...) heuristic
  • Enum type/variant names: now resolved from the embedded file_descriptor_set.bin via prost_reflect::DescriptorPool, replacing Rust AST reconstruction
  • parse_unknown: now uses ReflectMessage::descriptor() to enumerate fields and DynamicMessage for presence detection, replacing direct struct field inspection
  • Traversal entry points (parse_proto, validate): now bound on prost::Name + ReflectMessage instead of InputNode, enabling future use of externally-generated proto types without requiring ProtoMeta derived on them
  • NodeType::ProtoMessage changed from &'static str to String, removing the need for Box::leak or Lazy caching at node-creation sites

Motivation

This is groundwork toward consuming the substrait-prost crate (see #531) without needing to dynamically parse Rust code to reconstruct protobuf metadata. The previous approach reverse-engineered prost's naming conventions at compile time; this approach uses authoritative runtime reflection.

🤖 Generated with Claude Code

vbarua and others added 8 commits June 30, 2026 15:34
Enable prost-build's type_names feature so all generated message types
implement prost::Name. The ProtoMeta derive macro now calls
prost::Name::full_name() instead of the brittle cook_path() heuristic
which reconstructed proto type names from Rust module paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add prost-reflect as a dependency and configure prost-build to emit a
file descriptor set at build time. Expose a global DESCRIPTOR_POOL in
input::proto, loaded from the embedded descriptor bytes, for use by
runtime proto introspection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the case-convention heuristics in ProtoMeta's enum derive with
descriptor pool lookups. Enum type names now come from
EnumDescriptor::full_name() and variant names from
EnumValueDescriptor::name(), using Box::leak to satisfy the &'static str
return type. The cook_path result is still used as the initial pool
lookup key since prost-build does not generate Name impls for enums.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ssage

The ProtoMeta derive macro no longer inspects struct field types at
compile time to generate parse_unknown. Instead, each message now
implements prost_reflect::ReflectMessage (via a generated descriptor()
method), and parse_unknown enumerates unparsed fields at runtime using
MessageDescriptor::fields(). DynamicMessage is used to check field
presence before reporting unknowns.

Removes the FieldType enum and is_repeated helper from the derive crate.
Adds push_unknown_proto_field to traversal and field_descriptor_to_node
to input::proto for constructing tree nodes from FieldDescriptor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Oneof variant names and enum type names are always PascalCase identifiers,
never Rust keywords, so the r# stripping in cook_ident is unnecessary.
Replace cook_ident calls with plain ident.to_string() and remove the
helper entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ssage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…+ ReflectMessage

- NodeType::ProtoMessage now holds String instead of &'static str, removing the
  need for Box::leak or Lazy caching at node-creation sites
- parse_proto_message_unknown extracted from derive macro into traversal.rs as a
  standalone generic function; derive's InputNode::parse_unknown delegates to it
- parse_proto and validate now require prost::Name + ReflectMessage instead of
  InputNode, so proto message types from substrait-prost can be passed to these
  entry points without needing InputNode derived on them

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant