Adds a per-context routing layer for InfoBlock parsers, so different
peers can be routed to different parser sets (e.g. standard GB/T 32960
vs. a vendor extension that adds blocks in the 0x30~0x7F reserved range).
New types in protocol-gb32960:
- Gb32960ParserContext (record): version + vin + platformAccount tuple
- codec/profile/VendorExtensionCatalog: name -> list of vendor parsers
- codec/profile/Gb32960ProfileRegistry: name -> InfoBlockParserRegistry,
with a default registry built from the standard parsers and one extra
registry per enabled vendor extension (default + vendor parsers)
- codec/profile/VendorExtensionSelector: interface returning the matching
extension name (or null) for a given context
- codec/profile/RuleBasedVendorExtensionSelector: top-down first-match
scan over Gb32960Properties.vendorExtensions with a (account,vin)
cache keyed on case-insensitive normalized form
Gb32960Properties gains a `vendorExtensions` list with per-entry
`name` + `match` (platformAccounts / vins / vinPrefixes). All matching
fields are OR'd within an entry; entries are scanned top-down with
first-match-wins as documented.
Gb32960BodyParser keeps its legacy single-registry constructor for
back-compat (used by existing tests) and adds a new constructor that
takes the profile registry + selector. The parse loop now lives under
parse(Gb32960ParserContext, ByteBuffer); the legacy parse(version,body)
delegates to it with a minimal context (selector returns null -> default).
This commit only introduces the framework. Vendor parsers, autoconfig
wiring, and decoder/handler context plumbing land in follow-ups.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Captures the themed work that was rolled into the initial import commit
(login-ack time fix, idle handler, parser package split, removal of the
non-standard V2016 0x30 fuel cell stack registration, body-dump diagnostic
enhancement) so the history exists somewhere even though git can't carry
the per-theme commits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>