feat: DevEx P0 quick wins — TryFormat, AsTrimmedSpan, header helpers#157
Merged
Conversation
…153 #155 #156) Three additive features identified in the post-1.3.0 DevEx review against the real-world SbeB3UmdfConsumer. All three eliminate allocations or hardcoded constants on consumer hot paths — emit-time changes only, no codegen size or runtime cost change for existing call sites. #155 - AsTrimmedSpan() on InlineArray char types Consumers of FIX-style space-padded fields (Symbol, Currency, ISIN) were forced into msg.Field.ToString().Trim() — two allocations per read on hot path. AsTrimmedSpan() additionally strips trailing spaces beyond what AsSpan() already trimmed (\0). #153 - ISpanFormattable on char types and decimal composites - Char types implement TryFormat using the schema's characterEncoding (Latin1/UTF-8) over AsTrimmedSpan(). - Decimal composites use the existing Decimals constant for a default format string (e.g. F4) so consumers get correctly-scaled output without allocating in string.Create / Utf8.TryWrite paths. - Both also implement ToString(format, provider) for IFormattable. #156 - Static header read helpers on the messageHeader composite Consumers customizing dispatch were hardcoding 'SbeHeaderSize = 8' and reading the templateId via MemoryMarshal.Read at offset 2 — magic numbers that break if the schema customizes headerType. Now the generated header composite (detected via context.HeaderType, case-insensitive) exposes: public static bool TryReadTemplateId(ReadOnlySpan<byte>, out ushort) public static bool TryReadHeader(ReadOnlySpan<byte>, out blockLength, out templateId, out schemaId, out version) Both delegate to the field accessors, so endian conversion and any custom headerType field set are handled correctly. Detection: emit gate is the ordinal-case-insensitive name match between the composite name and SchemaContext.HeaderType, plus presence of all four standard fields (BlockLength/TemplateId/SchemaId/Version). Tests: 10 new integration tests in DevExFeatureTests.cs covering all three features. Snapshot updated for TypesCodeGenerator MessageHeader composite. 187 + 138 tests green. Bumps to 1.4.0. Closes #153, #155, #156. #154 (foreach enumerator) remains in P0 backlog — separate PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Apr 25, 2026
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.
Closes #153 #155 #156.
Three additive DevEx features identificadas no review pós-1.3.0 contra o consumer real (
SbeB3UmdfConsumer). Todas eliminam alocações ou constantes hardcoded em hot path do consumer. Emit-time only, sem custo runtime para call sites existentes.#155 —
AsTrimmedSpan()em InlineArray char typesConsumer fazia
msg.Symbol.ToString().Trim()(2 allocs por leitura) para FIX padding. Agora:#153 —
ISpanFormattableem char types e decimal compositesAsTrimmedSpan()+Encoding.X.GetChars(Latin1 ou UTF-8 conforme schema).Decimals(já gerado em Emit derived constants for primitive types: exponent, decimals, NULL_VALUE #145) como formato default —F4/F8etc., sem string interpolation.Implementa
TryFormat+ToString(format, provider)(IFormattable).#156 — Helpers estáticos no header composite
Consumer hardcoda
SbeHeaderSize = 8e lêtemplateIdvia offset mágico. Agora:Detecção: composite cujo nome bate (ordinal-case-insensitive) com
SchemaContext.HeaderType, e que tem os 4 campos padrão (BlockLength/TemplateId/SchemaId/Version). Os helpers delegam às properties — endian conversion e headerTypes customizados são respeitados.Testes
10 novos integration tests em
DevExFeatureTests.cs, snapshot atualizado emTypesCodeGenerator.Composite.MessageHeader.verified.txt. 187 + 138 verdes.Versão
Bump para 1.4.0 (3 features aditivas, sem break).
Não inclui
#154 (foreach enumerator para groups) — fica em PR próprio, é mudança maior no pipeline de
AppendReadGroups.