Skip to content

[Rust] MessageRegistry::from_descriptors for sibling/imported types (PR #461 feedback)#1

Open
pixie79 wants to merge 2 commits into
mainfrom
registry-from-descriptors
Open

[Rust] MessageRegistry::from_descriptors for sibling/imported types (PR #461 feedback)#1
pixie79 wants to merge 2 commits into
mainfrom
registry-from-descriptors

Conversation

@pixie79

@pixie79 pixie79 commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

Adds MessageRegistry::from_descriptors (behind the zeroparser feature) and addresses the review feedback from upstream databricks/zerobus-sdk#461.

from_descriptor only recurses nested_type, so it registers the root and its nested children but never the sibling/imported top-level messages from other files in a FileDescriptorSet. A root field typed e.g. .google.protobuf.StringValue then misses on registry.get() and decode fails with UnknownTypeName. from_descriptors(root, others) closes that gap by additionally registering each other top-level message under its true package-qualified FQN.

Feedback addressed

  1. True e2e coveragecreate_registry_for_version now builds the registry via from_descriptors, threading every top-level message in the compiled FileDescriptorSet (including the imported google.protobuf types) under its package-qualified FQN. The former negative test test_google_protobuf_types_not_in_registry is replaced by test_google_protobuf_types_decode_success, which decodes a GoogleProtobufTypesMessage and asserts Timestamp, Duration, and every wrapper type (StringValue, Int32Value, Int64Value, UInt32Value, UInt64Value, FloatValue, DoubleValue, BoolValue, BytesValue) plus repeated Timestamp resolve and decode correctly — for both proto2 and proto3, using the real descriptor-set path.
  2. Borrowed strings — API is now others: &[(&str, &DescriptorProto)]; call sites/tests updated.
  3. Trimmed rustdoc — the verbose doc comment on from_descriptors is reduced to a concise summary.
  4. Benchmarks — ran the existing Criterion parser bench before/after; see below.

Tests

cargo test -p databricks-zerobus-ingest-sdk --features zeroparser --lib zeroparser::registry   # 6 passed
cargo test -p databricks-zerobus-ingest-sdk --features zeroparser --test zeroparser_e2e        # 98 passed
cargo clippy --all --all-features -- -D warnings                                               # clean
cargo fmt --check                                                                              # clean

Benchmark evidence

cargo bench -p databricks-zerobus-ingest-sdk --features zeroparser --bench zeroparser_parser_bench -- --save-baseline before   # on 80fcd0b (base)
cargo bench -p databricks-zerobus-ingest-sdk --features zeroparser --bench zeroparser_parser_bench -- --baseline before        # with this change

The change touches only from_descriptors and the test-only registry helper — none of it is in the benchmark's decode b.iter loop, so no code-attributable change is expected. The comparison confirms this: all three decoders (prost, prost_reflect, and zeroparser) moved together by a uniform ~40–50% between the two runs, the signature of environmental variance (the base run executed under higher load) rather than a real effect on the byte-identical parser hot path. Net: no regression in the parser.

🤖 Generated with Claude Code

pixie79 and others added 2 commits June 30, 2026 20:34
…mported types

MessageRegistry::from_descriptor recurses only nested_type, so it registers
the root message and its nested children but never the sibling or imported
top-level messages from other files in a FileDescriptorSet. A root field
typed e.g. `.google.protobuf.StringValue` (from google/protobuf/wrappers.proto)
therefore misses on registry.get() and parsing fails with
`UnknownTypeName: Unknown message type '.google.protobuf.StringValue' not in
registry` on every record that populates such a field.

Add `from_descriptors(root, others)` which keeps the root as the parse root
(unchanged from_descriptor behaviour) and additionally registers every other
top-level message under its TRUE package-qualified FQN with a leading dot, by
threading the proto package as the initial prefix through the existing
collector. `collect_messages` now delegates to a `collect_messages_with_prefix`
helper so the prefix-threading is shared; the public `from_descriptor` API is
byte-for-byte unchanged.

Includes unit tests covering sibling registration under a non-empty package,
the empty-package (root-prefix) case, and nested-type collection on siblings.

Signed-off-by: Mark Olliver <mark.olliver@flutter.com>
Borrow the package strings in the from_descriptors API
(`others: &[(&str, &DescriptorProto)]`), trim the verbose rustdoc to a
concise summary, and update the two unit-test call sites.

Add true end-to-end coverage: create_registry_for_version now builds the
registry via from_descriptors, threading every top-level message in the
compiled FileDescriptorSet (including the imported google.protobuf types)
under its package-qualified FQN. The former negative test
test_google_protobuf_types_not_in_registry becomes
test_google_protobuf_types_decode_success, decoding a
GoogleProtobufTypesMessage and asserting Timestamp, Duration and every
wrapper type resolve and decode correctly for both proto2 and proto3.

Add a NEXT_CHANGELOG entry for the new zeroparser API.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Mark Olliver <mark.olliver@flutter.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