Table of Contents

Language feature and operation table

Use this table when you know a language feature but need to confirm which operations support it.

  • V means the behavior is verified without a special limitation.
  • L means the operation is supported with the limitation explained below.
  • — means the operation does not make sense for that feature, such as asking a scalar integer for a dynamic length.

The maintained feature-operation-matrix.json contains the same rows plus exact test methods, round-trip conditions, and limitation text used by repository validators.

Feature support

Feature/manual Parse Debug Address Length Serialize Write Update Read value Executable pair
Three-byte integers V V V V V V V V integers-24
Byte-bounded text encodings V V V V V V V V bounded-encodings
Width-bounded LEB128 integers V V V V V V L V leb128-integers
Exact fixed-point values V V V — V V V V fixed-point-values
UUID and Windows GUID values V V V V V V V V identifier-values
Conditional fields and tagged records V V V V V V L V conditional-fields
Fixed primitives V V V — V V V V fixed-primitives
Character buffers V V V V V V V V character-buffers
Terminated strings V V V V V V L V terminated-strings
Enums V V V — V V V V enums
Portable bitfields V V V — V V V V portable-bitfields
Fixed arrays V V V V V V V V fixed-arrays
Runtime expression arrays V V V V V V V V runtime-expression-arrays
Named nested structs V V V — V V V V nested-structs
Inline structs V V V — V V V V inline-structs
Typedefs V V V — V V V V typedefs
Unions V V V — V V V V unions
Pointers L V V — L L V L pointers
Multi-level pointers V L V — V V V V multi-pointers
Alignment/endian V V V — V V V V alignment-and-endian-overrides
Bounded failures V V V V V V V V bounded-failures
Invalid layouts V V V V V V V V invalid-layouts

Each pair in manual-fixtures-v1.json contains a valid layout with exact bytes, offsets, and values plus one invalid case and its stable error category. Tests execute the pairs on .NET 8 and .NET 10.

Operation meanings

Column What the operation does
Parse Reads a dynamic root or selected composite from a stream/span/memory
Debug Performs a read and records byte ranges for visited values
Address Finds a path's absolute stream position and restores caller position
Length Counts a fixed/runtime array or terminated string
Serialize Creates an array or writes to a span / IBufferWriter<byte>
Write Encodes a root/selected value at the current stream position
Update Finds and replaces storage after staged validation
Read value Returns one direct value or checked typed mapping

Every row is also compiled by the [CStructLayout] source generator: the matrix records "generated": "parity" for a feature whose fixture the parity project (tests/CStructSharp.Generated.Parity) generates and compares with the runtime - values, serialized bytes, addresses, and the failure at every truncated length - and the validator checks that claim against the project's layout index. All 47 features are at parity; the generated code series shows what each becomes in C#.

Supported does not mean equally appropriate. Memory input avoids a stream adapter when bytes are already available. Debugging adds diagnostic work. Updating has validation-before-commit behavior that a direct stream write does not. Use Choose an API for those tradeoffs.

The awaitable forms (ParseAsync and the other *Async reads, WriteAsync, UpdateAsync, ParseManyAsync, and the generated Parse<Name>Async/Write<Name>Async/Records<Name>Async), the ReadOnlySequence<byte> inputs, and the record sequences (ParseMany, the generated Records) add no column: each is an input or enumeration form of an operation above and runs the same reader, so every row's status carries over. The matrix's asyncContract block states the one rule they share (the stream is read with ReadAsync into a pooled buffer and the synchronous span reader runs over it), the position each form leaves a stream at, which forms need a seekable stream, where a stored pointer address counts from, and how cancellation surfaces, each with the test that pins it; memoryIoContract.inputApis lists the sequence overloads beside the span and memory ones. The guides are async and pipelines and, for the generated forms, sequences and TryParse.

Limited rows

A terminated-string update cannot grow beyond the existing storage plan or move later fields.

Pointer parsing, selected reads, and writes require explicit coordinate and following rules. Serialization writes addresses; it does not relocate target objects. Multi-level-pointer debugging records pointer storage but does not add a separate final primitive target range on every route.

Binary metadata type limits

  • Three-byte integers: No enum or bitfield backing; alignment is 1.

  • Byte-bounded text encodings: Counts are encoded bytes; strict decoding; shorter writes zero-pad. One-dimensional bounded arrays only.

  • Width-bounded LEB128 integers: Legal padded reads are accepted; canonical writes can change byte width. Updates require unchanged encoded extent. Static size is unknown.

  • Exact fixed-point values: No rounding, integer-expression projection, enum backing or bitfield backing.

  • UUID and Windows GUID values: Storage order is chosen by the type, not layout endianness. Identifiers cannot supply integer expressions.

  • Conditional fields and tagged records: Only active fields exist. Inactive selection fails and updates cannot change branch decisions or storage ranges. Update validation reads the complete root.