Conversation
`CodecStrategy::Table` generates a message's binary `Message` impl from a static `buffa::table::Table` and the shared interpreters, instead of code specialised to its fields. `CodecStrategy::Unrolled` stays the default. The strategy is set globally with `Config::codec_strategy` (plugin option `codec_strategy=`) and per message with `Config::codec_strategy_in` (plugin option `codec_strategy_in=<path>=<strategy>`, repeatable). Paths use the same prefix matching as the other `_in` rules, and the last matching rule wins. A table refers to the tables of its children, so a planner selects the largest set of requested messages that can use it: oneofs, maps, groups, custom representations, and messages that hold a message outside the set stay unrolled. A rule that selects such a message warns, the global setting produces one summary warning, and a rule that names the message by its exact path is an error. buffa-test compiles the same schemas with both strategies and checks that they encode to the same bytes and decode to the same values, including on truncated, bit-flipped, and random input.
|
All contributors have signed the CLA ✍️ ✅ |
Generated tables passed `::buffa::table::ABI` to `Table::new`, which compares its argument with the same constant, so the check could never fail. The generator now emits its own number, and a test keeps that number equal to the runtime's.
This was referenced Sep 23, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
CodecStrategy::Table, the generator for the table codec proposed in #463.Unrolledstays the default. Stacked on #468 (thebuffa::tableruntime), which is stacked on #467.The plugin takes
codec_strategy=tableand repeatablecodec_strategy_in=<path>=<strategy>. Rules match likepreserve_unknown_fields_in: prefix, last match wins, rules over the global setting. A message with aoneof,mapor group field, a custom string, bytes or collection type,MessageSet, or extension ranges with JSON stays unrolled, and so does every message that holds one.table_plan.rscomputes that closure and reports it in oneTableCodecFallbackSummarywarning, silent when the user's ownUnrolledrule is the cause. A rule that names such a message by its exact path is an error.compile()errors on rustc older than 1.77, and the MSRV job now also tests the table code on 1.77, so its timeout goes from 10 to 20 minutes.The 1,644 KB to 817 KB figure in #463 was measured with oneofs and maps flattened, so a real schema saves less until the follow-up that lets table messages hold unrolled, extern and well-known-type children.
The conformance suite does not run under
Table:TestAllTypesProto3has oneofs and maps, so its messages fall back. Parity rests onbuffa-test, which compiles each schema twice under renamed packages and compares bytes, sizes, decoded values and errors, including on truncated, bit-flipped and noise input. Under an experiment that set all 66buffa-testprotos toTable, 602 tests pass with 119 table messages.A table message differs from an unrolled one in three ways, documented in the guide: a length past the end of its enclosing message fails at once with
UnexpectedEof;merge_fieldcannot gather a non-contiguous buffer, so a type that another crate or run uses as a group orDELIMITEDfield must stayUnrolled; andclear()releases capacity. The generated code is tied tobuffa::table, so regenerate it wheneverbuffaupdates.About 1,300 lines are outside test files, well over the 250-line guideline.
Followed by #475 (message fields that hold messages without a table), #476 (
oneof) and #477 (map), stacked in that order.