Skip to content

Add batch primitives and generated accessors - #22

Merged
RejectKid merged 1 commit into
masterfrom
batch-primitives-and-generated-accessors
Jul 22, 2026
Merged

Add batch primitives and generated accessors#22
RejectKid merged 1 commit into
masterfrom
batch-primitives-and-generated-accessors

Conversation

@RejectKid

Copy link
Copy Markdown
Owner

Summary

  • add checked, allocation-free BitBatchPrimitives APIs for packed and record-strided reads and writes
  • cover all supported signed/unsigned integral types, native integers, Booleans, and LSB/MSB order with 88 symmetric overloads
  • validate the complete batch before processing and use bounded tail handling so exact-size buffers need no unsafe padding
  • add opt-in BitObjectAttribute.GenerateBatchAccessors generation for strongly typed integral, Boolean, and enum helpers
  • generate packed and strided static readers plus writers for non-readonly fields while preserving declared accessibility
  • keep generated batch helpers checked even when instance accessors opt into unsafe mode
  • document direct and generated usage, validation rules, and the maintained-fork feature overview
  • add functional, generator, boundary, API-surface, and performance coverage

Example

[BitObject(BitOrder.LeastSignificant, GenerateBatchAccessors = true)]
public partial struct Packet
{
    [BitField("Id", 12, BitFieldType.UInt16)]
    [BooleanField("Enabled")]
    private ushort _layout;
}

Packet.ReadIdBatch(records, bitStride: 16, destination: ids);
Packet.ReadEnabledBatch(records, bitStride: 16, destination: enabled);
Packet.WriteIdBatch(records, bitStride: 16, values: ids);

Performance

AMD Ryzen 9 9900X, .NET 10.0.8, BenchmarkDotNet MediumRun with 15 measured iterations, 10 warmups, and 2 launches. Values are normalized per field; all cases allocate 0 B.

12-bit UInt32 operation Scalar loop Direct batch Generated batch Result
Packed read 0.8177 ns 0.7882 ns 0.7788 ns direct 3.6% faster; generated 4.8% faster
32-bit-strided read 0.8586 ns 0.7697 ns 10.4% faster
Packed write 2.7427 ns 2.7273 ns 2.7368 ns effectively tied

The generated wrapper is fully inlined and adds no measurable overhead. Write batching is included for API symmetry and ergonomics; the measured difference is within noise.

Validation

  • Release solution build: 0 warnings, 0 errors
  • .NET 8 tests: 4,602 passed
  • .NET 10 tests: 4,602 passed
  • randomized/reference-equivalence coverage for every integral reader, both bit orders, packed/strided layouts, signed values, Booleans, enums, exact-size tails, and invalid ranges
  • generated packed/strided reader and writer coverage, including readonly behavior
  • public API reflection audit: 44 read and 44 write overloads
  • focused BenchmarkDotNet MediumRun: passed, 0 B allocated
  • NuGet pack and validation using 1.6.0-preview.2: passed
  • targeted formatting verification and git diff --check: passed

@RejectKid
RejectKid marked this pull request as ready for review July 22, 2026 15:03
@RejectKid
RejectKid merged commit 7b60ce4 into master Jul 22, 2026
8 checks passed
@RejectKid
RejectKid deleted the batch-primitives-and-generated-accessors branch July 22, 2026 15:13
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