whfmt.SourceGenerator
1.0.0
dotnet add package whfmt.SourceGenerator --version 1.0.0
NuGet\Install-Package whfmt.SourceGenerator -Version 1.0.0
<PackageReference Include="whfmt.SourceGenerator" Version="1.0.0" />
<PackageVersion Include="whfmt.SourceGenerator" Version="1.0.0" />
<PackageReference Include="whfmt.SourceGenerator" />
paket add whfmt.SourceGenerator --version 1.0.0
#r "nuget: whfmt.SourceGenerator, 1.0.0"
#:package whfmt.SourceGenerator@1.0.0
#addin nuget:?package=whfmt.SourceGenerator&version=1.0.0
#tool nuget:?package=whfmt.SourceGenerator&version=1.0.0
whfmt.SourceGenerator
Roslyn Source Generator that turns .whfmt binary format definitions into strongly-typed C# parsers at compile time — no CLI step, no checked-in generated files, full IntelliSense.
Quick start
1. Install
<PackageReference Include="whfmt.SourceGenerator" Version="1.0.0" />
2. Declare your .whfmt file as an AdditionalFile
<ItemGroup>
<AdditionalFiles Include="Formats\PNG.whfmt" />
</ItemGroup>
3. Use the generated parser — no other step needed
using WhfmtGenerated;
var png = PngParser.ParseFile("image.png");
Console.WriteLine($"{png.Width} x {png.Height}"); // strongly-typed fields
The class PngParser (and its typed fields) appear automatically every time the project builds. The .g.cs file is never committed to source control.
Configuration
Each AdditionalFiles entry accepts per-file MSBuild metadata to control generation:
| Metadata key | Default | Description |
|---|---|---|
WhfmtNamespace |
WhfmtGenerated |
C# namespace for the generated class |
WhfmtClass |
File name in PascalCase | Class name override |
WhfmtLanguage |
CSharp |
Output language (see below) |
WhfmtValidate |
true |
Emit signature + checksum validation |
WhfmtAsync |
false |
Emit ParseAsync(Stream, CancellationToken) overloads |
Example — custom namespace + async overloads
<AdditionalFiles Include="Formats\ZIP.whfmt">
<WhfmtNamespace>MyApp.Formats</WhfmtNamespace>
<WhfmtClass>ZipParser</WhfmtClass>
<WhfmtValidate>true</WhfmtValidate>
<WhfmtAsync>true</WhfmtAsync>
</AdditionalFiles>
var zip = await ZipParser.ParseAsync(stream, cancellationToken);
Console.WriteLine(zip.LocalFileHeaders.Count);
Supported output languages
WhfmtLanguage value |
Generated output |
|---|---|
CSharp (default) |
class with BinaryReader, rich enums, nullable conditionals, List<T> repeating fields |
CSharpSpan |
ref struct with ReadOnlySpan<byte> + MemoryMarshal — zero heap allocations |
FSharp |
F# module with discriminated unions and parse function |
Rust |
Rust struct + impl TryFrom<&[u8]> |
VisualBasic |
VB.NET Class with BinaryReader |
Note: F#, Rust and VB output is supported but the generated
.g.csfile will contain the foreign-language source as a string literal comment — use the whfmt-codegen CLI for those targets instead.
Multiple formats at once
Apply settings to all .whfmt files in a folder:
<ItemGroup>
<AdditionalFiles Include="Formats\*.whfmt">
<WhfmtNamespace>MyApp.Formats</WhfmtNamespace>
<WhfmtValidate>true</WhfmtValidate>
</AdditionalFiles>
</ItemGroup>
Each file gets its own generated class named after the file (PascalCase).
Zero-alloc Span variant
For performance-critical paths (hot loops, network buffers):
<AdditionalFiles Include="Formats\PNG.whfmt">
<WhfmtNamespace>MyApp.Formats</WhfmtNamespace>
<WhfmtLanguage>CSharpSpan</WhfmtLanguage>
</AdditionalFiles>
ReadOnlySpan<byte> buffer = stackalloc byte[128];
// ... fill buffer ...
var png = new PngParser(buffer);
Console.WriteLine(png.Width); // no allocation
Global configuration via Directory.Build.props
Apply settings to all .whfmt files across the entire project tree without repeating metadata on every <AdditionalFiles> entry:
<Project>
<ItemGroup>
<AdditionalFiles Include="$(MSBuildProjectDirectory)\Formats\*.whfmt">
<WhfmtNamespace>$(RootNamespace).Formats</WhfmtNamespace>
<WhfmtValidate>true</WhfmtValidate>
</AdditionalFiles>
</ItemGroup>
</Project>
Individual projects can still override per-file:
<AdditionalFiles Include="Formats\Internal.whfmt">
<WhfmtNamespace>$(RootNamespace).Internal</WhfmtNamespace>
<WhfmtAsync>true</WhfmtAsync>
</AdditionalFiles>
What gets generated
For a .whfmt file with blocks like:
{
"formatName": "PNG",
"blocks": [
{ "name": "Signature", "offset": 0, "length": 8, "type": "bytes", "isSignature": true },
{ "name": "Width", "offset": 16, "length": 4, "type": "uint32", "endian": "big" },
{ "name": "Height", "offset": 20, "length": 4, "type": "uint32", "endian": "big" },
{ "name": "BitDepth", "offset": 24, "length": 1, "type": "byte" }
]
}
The generator emits:
// <auto-generated/>
// Source: PNG.whfmt (whfmt.SourceGenerator)
namespace WhfmtGenerated;
public sealed class PngParser
{
public byte[] Signature { get; }
public uint Width { get; }
public uint Height { get; }
public byte BitDepth { get; }
private PngParser(BinaryReader r) { /* ... */ }
public static PngParser Parse(Stream stream) { /* ... */ }
public static PngParser Parse(byte[] data) { /* ... */ }
public static PngParser ParseFile(string path) { /* ... */ }
}
Fields with valueMap become enums. isRepeating fields become List<T>. isConditional fields become nullable.
Diagnostics
| Code | Severity | Meaning |
|---|---|---|
WHSG001 |
Error | The .whfmt file could not be parsed or contains an unsupported schema construct. Check the file follows whfmt v3 schema. |
Relationship to whfmt-codegen CLI
This package and whfmt.CodeGen (the global CLI tool whfmt-codegen) share the same generation engine.
whfmt.SourceGenerator |
whfmt.CodeGen CLI |
|
|---|---|---|
| Trigger | Automatic at build | Manual (whfmt-codegen generate) |
| Generated files committed? | No — lives in obj/ |
Yes — explicit output |
| Best for | C# / C#Span in .NET projects | F#, Rust, VB, one-shot generation |
| IntelliSense | ✅ Full | ✅ After running CLI |
| Multi-format glob | ✅ Via <AdditionalFiles> |
One at a time |
Requirements
- .NET SDK 6.0 or later (Roslyn incremental generator support)
.whfmtfiles following whfmt v3 schema — see whfmt.FileFormatCatalog for 800+ ready-to-use definitions
License
GNU AGPL v3.0 — see LICENSE.
Learn more about Target Frameworks and .NET Standard.
This package has 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.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 31 | 5/21/2026 |