Stardust.Utilities
0.9.12
dotnet add package Stardust.Utilities --version 0.9.12
NuGet\Install-Package Stardust.Utilities -Version 0.9.12
<PackageReference Include="Stardust.Utilities" Version="0.9.12" />
<PackageVersion Include="Stardust.Utilities" Version="0.9.12" />
<PackageReference Include="Stardust.Utilities" />
paket add Stardust.Utilities --version 0.9.12
#r "nuget: Stardust.Utilities, 0.9.12"
#:package Stardust.Utilities@0.9.12
#addin nuget:?package=Stardust.Utilities&version=0.9.12
#tool nuget:?package=Stardust.Utilities&version=0.9.12
Stardust.Utilities
Zero-cost bit manipulation, Rust-style error handling, endian-safe integers, and fixed-width 256-bit math for modern .NET. One NuGet package. One source generator. No runtime dependencies.
Stardust.Utilities is a library, not a framework. You pick the pieces you need and use them exactly where you need them -- parsing a packet, decoding a register, shaping an API result. Nothing runs on its own, nothing calls home, and nothing ships with your binary except the code you touch.
Table of Contents
- Why Stardust.Utilities?
- See It In One Snippet
- Try It Live
- Installation
- What's In The Box
- Features
- Compatibility
- Common Gotchas
- What's New
- License
- Contributing
- Security
- Privacy
Why Stardust.Utilities?
- Zero abstraction penalty. Source-generated
[BitFields]types compile to the same IL as hand-coded shift/mask -- benchmark is statistically identical to raw bit manipulation across 160 independent runs (BITFIELDS.md -- Performance). - Zero heap allocations. Every value-type operation -- arithmetic, parsing, formatting, JSON round-trips, span I/O -- is stack-only. Value types never box.
- Competitive 256-bit math.
UInt256/Int256match or beat the leading managed 256-bit libraries on the operations that matter (add, sub, mul, div, parse, format). See the comparison table in the Large Integers section. - No runtime dependency. The source generator runs at build time and ships only as an analyzer. Your compiled app picks up nothing extra -- no second DLL, no reflection, no interface-based dispatch.
- Full modern .NET surface, generated for you.
IParsable<T>,ISpanParsable<T>,ISpanFormattable,System.Text.Json, full operator overloading, implicit conversions, span-based serialization -- all produced by the generator, not hand-written per struct. - Rust-inspired ergonomics, no religion.
Result<T, TError>andOption<T>live alongside normal exceptions. Use them where they fit; don't let them take over the codebase. - Runs everywhere .NET 7+ runs. Multi-targets
net7.0/net8.0/net9.0/net10.0. Tested on x64, ARM64, and big-endian architectures (via QEMU in CI).
If you have ever hand-rolled a bit-packed protocol header, juggled BinaryPrimitives.ReverseEndianness, or written the same if (result.IsOk) ... else ... boilerplate for the twentieth time -- this package removes that code.
See It In One Snippet
Parse a live IPv4 header straight out of the packet buffer, zero copies:
using Stardust.Utilities;
// Define the RFC 791 layout once. No hand-written shift/mask anywhere.
[BitFields(ByteOrder.BigEndian, BitOrder.BitZeroIsMsb)]
public partial record struct IPv4Header
{
[BitField(0, 3)] public partial byte Version { get; set; }
[BitField(4, 7)] public partial byte IHL { get; set; }
[BitField(8, 15)] public partial byte TypeOfService{ get; set; }
[BitField(16, 31)] public partial ushort TotalLength { get; set; }
[BitField(64, 71)] public partial byte TTL { get; set; }
[BitField(72, 79)] public partial byte Protocol { get; set; }
[BitField(96, 127)] public partial uint SourceIP { get; set; }
}
// Read directly from the packet. No allocations, no copies.
byte[] packet = ReceiveFromNetwork();
var hdr = new IPv4Header(packet);
if (hdr.Version == 4 && hdr.Protocol == 6)
Console.WriteLine($"TCP packet, length {hdr.TotalLength}, TTL {hdr.TTL}");
The generator emits inline bit-shift/mask property implementations with compile-time constants. There is no runtime reflection, no boxing, and no allocation. See BITFIELDS.md for the full model.
Try It Live
Launch the interactive web demo -- explore [BitFields], PE headers, network packets, CPU registers, and RFC diagrams directly in your browser. No install required.
Prefer video? Watch a walkthrough of the demo app.
| RFC bit-field diagram | PE header viewer | Composable floating-point lab |
|---|---|---|
![]() |
![]() |
![]() |
Installation
<PackageReference Include="Stardust.Utilities" />
That's it. NuGet restores the latest stable version; the badge above shows what that is today. To pin a specific version add Version="x.y.z" -- useful for reproducible builds, but most projects don't need it.
What's In The Box
| Feature | What it does | Deep dive |
|---|---|---|
| BitFields value types | Generate zero-cost bit-packed structs with operators, parsing, JSON, and span I/O | BITFIELDS.md |
| BitFields zero-copy views | Read/write bits directly on a Memory<byte> buffer -- no copies |
BITFIELDS.md |
| Result<T, TError> / Result<TError> | Explicit railway-oriented error handling without exceptions | RESULT.md |
| Option<T> | Explicit optional values without null, zero-cost on the hot path |
OPTION.md |
| Endian types (16 through 256 bits) | Type-safe big- and little-endian integers that compile to a single BSWAP |
ENDIAN.md |
| UInt256 / Int256 | Fixed-width 256-bit arithmetic with native CPU instructions (BMI2, DivRem) | LARGE_INTEGERS.md |
| Hi / Lo / Saturating extensions | Upper/lower byte access and clamped arithmetic on every integer type | EXTENSIONS.md |
| RFC diagram generator | Render ASCII bit-field diagrams from any [BitFields] struct at runtime |
BITFIELDS.md -- RFC Diagram Generator |
| IEEE 754 / Decimal decomposers | Pre-built [BitFields] types for Half, float, double, decimal |
BITFIELDS.md -- Numeric Decomposition Types |
Features
BitFields
One attribute. Two struct kinds. Hardware-speed bit access with no boilerplate.
Annotate a partial struct for a self-contained value type, or a partial record struct for a zero-copy view over an external Memory<byte> buffer. Both use the same [BitField] / [BitFlag] property attributes and produce identical JSON and span I/O:
using Stardust.Utilities;
// Value type: backed by a storage primitive (byte, uint, ulong, UInt128, UInt256, ...)
[BitFields(StorageType.Byte)]
public partial struct StatusRegister
{
[BitFlag(0)] public partial bool Ready { get; set; }
[BitFlag(1)] public partial bool Error { get; set; }
[BitFlag(7)] public partial bool Busy { get; set; }
[BitField(2, End = 4)] public partial byte Mode { get; set; } // 3 bits
[BitField(5, End = 6)] public partial byte Priority { get; set; } // 2 bits
}
StatusRegister reg = 0x42;
reg.Ready = true;
reg.Mode = 5; // bits 2-4
byte raw = reg; // implicit conversion to storage type
var next = reg.WithPriority(2); // fluent, immutable-style update
string j = JsonSerializer.Serialize(reg); // "0x4D"
Proven zero-overhead (500M iterations, .NET 10 -- full methodology in BITFIELDS.md):
| Operation | Raw bit ops | Generated property | Difference |
|---|---|---|---|
| Boolean GET | 271 ms | 263 ms | ~0% (noise) |
| Boolean SET | 506 ms | 494 ms | ~0% (noise) |
| Field GET (shift+mask) | 124 ms | 123 ms | ~0% (noise) |
Choosing between the two shapes:
partial struct (value type) |
partial record struct (view) |
|
|---|---|---|
| Backing | Private value field | External Memory<byte> |
| Copy cost | Copies all data | Copies a 24-byte view header |
| Max size | ~16 KB (or up to 16,384 bits via [BitFields(N)]) |
Unlimited |
| Operators | Full arithmetic, bitwise, comparison | None (it is a view, not a value) |
| Typical use | Registers, opcodes, flags, network fields | Network packets, file headers, DMA buffers |
Key benefits:
- Identical-to-hand-coded performance, confirmed by statistical benchmarking.
- Full modern .NET surface generated per type:
IParsable<T>,ISpanParsable<T>,ISpanFormattable,IComparable<T>,IEquatable<T>,System.Text.Jsonconverter, span constructors,ReadFrom/WriteTo/TryWriteTo,ToByteArray. - Storage types from
byteup toUInt256, plus auto-sizing, plus arbitrary-width[BitFields(N)]from 1 to 16,384 bits. MustBe/UndefinedBitsMustBeenforce reserved-bit invariants at every entry point with under 1 ns construction overhead and zero getter overhead.- Composition: value types nest in views, views nest in views,
UInt256nests in anything -- each nested type carries its own byte/bit order.
See BITFIELDS.md for the complete attribute reference, storage types, composition rules, JSON/span I/O, compiler diagnostics, and real-world protocol examples.
Result Types
Railway-oriented error handling without exceptions. Inspired by Rust's Result<T, E>.
// Enable clean Ok() / Err() syntax via global using
global using static Stardust.Utilities.Result<int, string>;
Result<int, string> Divide(int a, int b) =>
b == 0 ? Err("Division by zero") : Ok(a / b);
var message = Divide(10, 2)
.Map(x => x * 2) // transform the value
.AndThen(x => Divide(x, 4)) // chain another Result
.Inspect(x => Console.WriteLine(x)) // side effect on success
.MapOrElse(
onOk: v => $"Answer: {v}",
onErr: e => $"Failed: {e}");
Key benefits:
- Explicit success/failure in the type signature -- impossible to forget error handling.
- Full monadic surface:
Map,MapErr,AndThen,OrElse,Inspect,InspectErr,Flatten,Transpose,MapOr,MapOrElse. - Interop with
Option<T>viaToOption/OkOr/Transpose. - Void form
Result<TError>for save/send/delete operations that succeed or fail but return nothing. - Works with
async/awaitend-to-end.
See RESULT.md for the full API, custom error types, real-world examples, and async patterns.
Option Types
Explicit optional values without null. Inspired by Rust's Option<T>.
global using static Stardust.Utilities.Option;
Option<int> ParsePositive(string s) =>
int.TryParse(s, out var n) && n > 0 ? Some(n) : None;
int port = ParsePositive(input).UnwrapOr(8080);
var email = GetUserById(id)
.AndThen(user => user.Email)
.Filter(e => e.Contains('@'));
Zero-cost on the hot path (100M iterations, .NET 10):
| Operation | Option<T> |
T? |
Difference |
|---|---|---|---|
| Create Some | 35 ms | 34 ms | ~0% (noise) |
IsSome check |
46 ms | 49 ms | ~0% (noise) |
UnwrapOr (??) |
122 ms | 127 ms | ~0% (noise) |
Key benefits:
- State checks, value extraction, and defaults are statistically identical to hand-written
T?code. - Delegate-based transforms (
Map,AndThen,Filter) add 1-2 ns -- fine outside tight inner loops. - Bidirectional interop with
Result<T, TError>. Noneas a static singleton means no allocation on theNonebranch.
See OPTION.md for the full API, performance analysis, interop patterns, and async support.
Endian Types
Type-safe endian-aware integers at native speed. 16 types covering 16 through 256 bits, big-endian and little-endian, signed and unsigned.
using Stardust.Utilities;
// Big-endian wire values with native arithmetic
UInt32Be seq = 0x12345678; // stored as 12 34 56 78
UInt32Be next = seq + 1; // arithmetic works natively
Span<byte> buf = stackalloc byte[4];
next.WriteTo(buf); // zero-allocation serialization
// Read back from a packet
var incoming = new UInt32Be(receivedBytes);
uint native = incoming; // implicit conversion
No performance penalty (BenchmarkDotNet, .NET 10):
| Width | Le vs. native |
Be vs. hand-coded BSWAP |
|---|---|---|
| 16-bit | 1.0x | 1.0x (single register rotate) |
| 32-bit | 1.0x | 1.0x (single BSWAP) |
| 64-bit | 1.0x | 1.0x (single BSWAP) |
| 128-bit | 1.0x | 1.0x (two BSWAPs + swap halves) |
| 256-bit | 1.0x | 7-19x faster than BigInteger-backed alternatives |
Key benefits:
[StructLayout(LayoutKind.Explicit)]guarantees byte ordering in memory regardless of host.- Full operator set: arithmetic, bitwise, shift, comparison, equality.
- Modern .NET interfaces generated:
IParsable<T>,ISpanParsable<T>,ISpanFormattable. - Zero-allocation
ReadOnlySpan<byte>constructors plusWriteTo/TryWriteTo. - PropertyGrid
TypeConverterfor every type. - Per-field endian override inside
[BitFields]views -- mix big- and little-endian fields in the same buffer.
See ENDIAN.md for the full type matrix, benchmark tables, migration guide from manual ReverseEndianness, and real-world examples.
Large Integers (256-bit)
Fixed-width 256-bit signed and unsigned integers that are competitive with the leading managed alternatives on every operation that matters.
UInt256 and Int256 fill the gap between the BCL's UInt128 / Int128 and the heap-allocated, arbitrary-precision BigInteger. They are the right tool for cryptographic digests, Ethereum / EVM-style values, large accumulators, GUID-scale identifiers, and any fixed-32-byte quantity that needs real arithmetic -- not just byte manipulation.
using Stardust.Utilities;
UInt256 a = 42;
UInt256 b = UInt256.Parse("115792089237316195423570985008687907853269984665640564039457584007913129639935");
UInt256 hash = (a * 31 + b) ^ UInt256.MaxValue;
// Zero-allocation wire I/O
ReadOnlySpan<byte> wire = ReceivePacket(); // 32 bytes, network order
UInt256Be be = new(wire);
UInt256 value = be; // implicit conversion to host-native
Competitive with the leading managed 256-bit libraries (.NET 10 x64, lower = faster; 1.00x is the Stardust baseline):
| Operation | Stardust.Utilities.UInt256 |
Nethermind.Numerics.Int256 1.5.0 |
MissingValues.UInt256 2.2.1 |
BigInteger (BCL) |
|---|---|---|---|---|
| Add | 1.00x | 1.49x | 1.00x | 38.5x |
| Sub | 1.00x | 1.70x | 1.00x | 46.3x |
| Mul | 1.00x | 1.73x | 1.01x | 25.3x |
| Div | 1.00x | 1.14x | 2.08x | 7.36x |
| Mod | 1.00x | 1.17x | 2.16x | 7.22x |
| ToString | 1.00x | 1.58x | 1.08x | 1.98x |
| Parse | 1.00x | 4.32x | 2.27x | 4.60x |
BigInteger allocates 2-3 MB per 10,000-iteration run and triggers GC; the 7-46x ratios reflect that cost, not raw throughput. All three fixed-width libraries are high-quality implementations. Library versions move -- re-run BenchmarkSuite1/Int256LibraryComparisonBenchmarks.cs against current packages if the decision matters.
Key benefits:
- Zero heap allocations on the hot path (
readonly structbacked by fourulongvalues). - Native CPU instructions: multiply via BMI2
MULX, divide viaX86Base.X64.DivRem, with hand-rolled carry-chain fallbacks on ARM64 and non-x64 platforms. - Full operator and interface surface -- drop-in replacement for
UInt128/BigIntegerwhere 32-byte fixed width is the right shape. - Wire-format safety via
UInt256Be/UInt256Lewith zero conversion cost on LE hardware. - First-class
[BitFields]citizen:[BitFields(typeof(UInt256))]gets a 4-ulong backing store with full operator and JSON support. - Fuzz-tested on every build:
Int256NativeArithmeticTestscross-validates every operation againstBigIntegeron randomized inputs.
See LARGE_INTEGERS.md for the full API, benchmark methodology, and guidance on choosing between UInt256, UInt128, and BigInteger.
Extension Methods
Upper/lower byte access and clamped arithmetic on every integer type, native or endian.
using Stardust.Utilities;
ushort word = 0x1234;
byte hi = word.Hi(); // 0x12
byte lo = word.Lo(); // 0x34
word = word.SetHi(0xFF); // 0xFF34
// Saturating arithmetic: clamps instead of overflowing
int r1 = int.MaxValue.SaturatingAdd(1); // int.MaxValue
uint r2 = 10u.SaturatingSub(20u); // 0
UInt256 r3 = UInt256.MaxValue.SaturatingAdd(new UInt256(1UL)); // UInt256.MaxValue
Int256 r4 = Int256.MinValue.SaturatingSub(new Int256(1L)); // Int256.MinValue
Key benefits:
- Works uniformly on native (
ushort...Int256), big-endian (UInt16Be...Int256Be), and little-endian types. Hi()/Lo()return the upper/lower half as the appropriate half-width type.SetHi()/SetLo()produce a new value -- no mutation, no allocation.SaturatingAdd/SaturatingSubclamp to the type's representable range.
See EXTENSIONS.md for the full method list and performance notes.
RFC Diagram Generator
Render RFC 2360-style ASCII bit-field diagrams from any [BitFields] struct at runtime.
var diagram = new BitFieldDiagram(typeof(IPv4HeaderView));
string output = diagram.RenderToString().Value;
// Render multiple structs in a single diagram with consistent scale
var combined = new BitFieldDiagram(
[typeof(M68020DataRegisters), typeof(M68020SR)],
description: "68020 Registers");
Console.WriteLine(combined.RenderToString().Value);
Cells auto-size to fit field names, byte offsets label each row, and undefined bits are clearly marked. See BITFIELDS.md -- RFC Diagram Generator for configuration options and examples.
Pre-Defined Numeric Types
Four pre-built [BitFields] types that decompose .NET numeric types into their constituent fields. Just using Stardust.Utilities; and start using them -- no struct definitions required.
| Type | Storage | Use case |
|---|---|---|
IEEE754Half |
Half (16-bit) |
Half-precision analysis |
IEEE754Single |
float (32-bit) |
Single-precision analysis |
IEEE754Double |
double (64-bit) |
Double-precision analysis |
DecimalBitFields |
decimal (128-bit) |
Decimal inspection |
IEEE754Double pi = Math.PI;
pi.Sign; // false
pi.BiasedExponent; // 1024 (raw stored value, includes +1023 bias)
pi.Exponent; // 1 (true mathematical power: 2^1, since 2 <= pi < 4)
pi.Mantissa; // 0x921FB54442D18
pi.IsNormal; // true
var rebuilt = IEEE754Double.Zero
.WithExponent(pi.Exponent!.Value)
.WithMantissa(pi.Mantissa);
double result = rebuilt; // == Math.PI
All four types include implicit conversions to and from their storage type, full operator support, classification properties (IsNormal, IsNaN, IsInfinity, IsDenormalized, IsZero), both the raw BiasedExponent field and a computed Exponent property that removes the bias, and a WithExponent(int) fluent method that sets the exponent from its true mathematical value.
See Numeric Decomposition Types in BITFIELDS.md for full details, bit-layout diagrams, constants, and classification reference.
Compatibility
| Dimension | Supported |
|---|---|
| Target frameworks | net7.0, net8.0, net9.0, net10.0 |
| Process architectures | x86, x64, ARM64 (nint/nuint diagnostics steer you around 32-bit pitfalls) |
| Host endianness | Little-endian (x86/x64/ARM) native; big-endian fully supported and CI-tested via QEMU |
| Runtime deps | None (source generator ships as an analyzer; no extra DLL in your output) |
| Trimming / AOT | Value types and generated code are trim-safe; no reflection on the hot path |
| Compiler requirement | C# 13+ (VS 2022 17.0+ for incremental generator support) |
Common Gotchas
Three most-frequent issues and their fixes. For the full diagnostic reference (every SD00xx error and warning, browser/WASM notes, how to view generated code) see TROUBLESHOOTING.md.
CS9248: partial property must have an implementation part-- add thepartialkeyword to every[BitField]/[BitFlag]property. If you also seeSD0004, the generator is pointing directly at the missing keyword.- Generated code didn't update -- make sure the type is
partial structorpartial record struct(notclass), then clean and rebuild. - IntelliSense missing for generated members -- build the project at least once, then close and reopen the solution if needed.
What's New
Every release gets a dated entry in CHANGELOG.md covering added features, behavior changes, deprecations, and backwards compatibility notes. On nuget.org the same information appears on the package's Release Notes tab.
License
MIT. See LICENSE.
Contributing
Contributions are welcome. Please read the guidelines before submitting issues or pull requests.
Security
To report a security vulnerability, please use GitHub's private vulnerability reporting feature. Do not report security issues through public GitHub issues. See SECURITY.md for details.
Privacy
Stardust.Utilities does not collect, transmit, or store any personal data, telemetry, or usage information. See PRIVACY.md for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net7.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v0.9.12 -- README-only re-release of v0.9.11. Removes hardcoded version strings from README.md that had drifted through the last two releases (install snippet is now versionless -- <PackageReference Include="Stardust.Utilities" /> -- and the "What's New" section now just links to CHANGELOG.md; the shields.io NuGet badge at the top displays the current version). Build-Combined-NuGetPackages.ps1 adds a new Step 3 that lints README.md for any remaining literal Version="x.y.z" or **vX.Y.Z** references against the bumped $Version and fails the build on mismatch. Library binaries, source, and public API are identical to v0.9.9 through v0.9.11.
v0.9.11 -- README-only re-release of v0.9.10. Fixes README links from the package front page (LARGE_INTEGERS.md, BITFIELDS.md, RESULT.md, OPTION.md, ENDIAN.md, EXTENSIONS.md, TROUBLESHOOTING.md, CHANGELOG.md, SECURITY.md, PRIVACY.md) that v0.9.10 left as relative paths; nuget.org's renderer does not follow relative links into the packed .nupkg, so clicks on those links bounced back to the README itself. v0.9.11 rewrites them at pack time to absolute, tag-pinned URLs of the form https://github.com/dhadner/Stardust.Utilities/blob/v0.9.11/<file>.md so they resolve on nuget.org while still pointing at *this version's* documentation. Library binaries, source, and public API are identical to v0.9.10. v0.9.10 has been unlisted; install v0.9.11 instead.
v0.9.10 -- README-only re-release of v0.9.9. Screenshot images in the package README now render on nuget.org (v0.9.9 used relative paths that nuget.org does not resolve against package contents). v0.9.9 has been unlisted; install v0.9.10 instead. Library binaries, source, and public API are identical to v0.9.9.
v0.9.9 feature additions (omitted from the original v0.9.9 release notes):
- UInt256 / Int256 value types: fixed-width 256-bit signed and unsigned integers backed by four ulongs. Zero heap allocation on the hot path. Multiply via BMI2 MULX (Bmi2.X64.MultiplyNoFlags); divide/mod/decimal extraction via the X86Base.X64.DivRem hardware intrinsic on x64 .NET 8+. Full operator set (+ - * / % and/or/xor/not/shifts/compare/++/--), parse (decimal and hex), format (D, G, R, X, x with precision), BigInteger interop, and conversions across byte through UInt128 / Int128. Implements IComparable, IEquatable, IFormattable, ISpanFormattable, IParsable, ISpanParsable. Benchmarks in LARGE_INTEGERS.md show competitive-or-better performance versus Nethermind.Numerics.Int256 1.5.0 and MissingValues 2.2.1 across add, sub, mul, div, mod, ToString, and Parse.
- UInt256Be / UInt256Le: 32-byte endian-aware wrappers for wire-format interop, with implicit conversion to/from host-native UInt256 and zero-allocation WriteTo / ReadFrom / TryWriteTo / ToByteArray.
- UInt256 and Int256 as [BitFields] storage types: StorageType.UInt256 (= 17) and StorageType.Int256 (= 16) are now first-class. The generator emits a 4-ulong backing store, full arithmetic, JSON, span I/O, fluent With... methods, and usage as embedded property types in zero-copy views.
- Auto-sized [BitFields] on value-type structs: omit the storage type and the generator picks the smallest unsigned type that covers all declared bits.
- Cross-type widening/narrowing conversions on all Little-Endian types (parity with Big-Endian): UInt16Le to UInt32Le/UInt64Le/UInt128Le and equivalents for signed / narrowing / Int16Le-to-UInt32Le / Int32Le(Int16Le) sign-extending.
- SaturatingAdd / SaturatingSub now cover every integer width (byte/sbyte through Int128/UInt128) and every endian type (16-128 bit, Be and Le).
- Hi / Lo / SetHi / SetLo now cover all native integer widths (ushort/short through UInt128/Int128) and all endian types.
- Missing operators added: *, /, %, &, |, ^, ~, >>, << on signed Le types (Int16Le/Int32Le/Int64Le); %, ^ on UInt32Le / UInt64Le; ++, --, %, ^, ~ on UInt32Be / Int32Be. All 16 endian types now have the complete operator set, including unsigned right shift (>>>).
- Endian types now run at native CPU speed on little-endian hardware and compile to a single BSWAP per Be conversion. 16-bit types use an overlapping [FieldOffset(0)] _value field; 32-bit and wider use Unsafe.As for zero-cost reinterpretation.
- [MethodImpl(AggressiveInlining)] on every operator and conversion operator of every Be/Le type.
- BIT_WIDTH constant on all generated [BitFields] types.
- StructDescription / StructDescriptionResourceType on record struct views (previously value-type only).
- UndefinedBits on [BitFields] is now settable as a named argument (useful with auto-sized structs where there is no constructor parameter).
v0.9.9 breaking change (additive otherwise): generator-emitted private members are now prefixed with `__` (Value -> __value, _w0/_w1 -> __w0/__w1, _data -> __data, _bitOffset -> __bitOffset, and all per-field constants like MODE_MASK / MODE_START_BIT -> __MODE_MASK / __MODE_START_BIT). Only affects code that touched generator-emitted privates via reflection or Unsafe.
See CHANGELOG.md in the package for the full list.


