FlatBufferLite.SourceGen 0.0.3

dotnet add package FlatBufferLite.SourceGen --version 0.0.3
                    
NuGet\Install-Package FlatBufferLite.SourceGen -Version 0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FlatBufferLite.SourceGen" Version="0.0.3">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FlatBufferLite.SourceGen" Version="0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="FlatBufferLite.SourceGen">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FlatBufferLite.SourceGen --version 0.0.3
                    
#r "nuget: FlatBufferLite.SourceGen, 0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FlatBufferLite.SourceGen@0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FlatBufferLite.SourceGen&version=0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=FlatBufferLite.SourceGen&version=0.0.3
                    
Install as a Cake Tool

FlatBufferLite

Disclaimer: This library was written by AI and almost certainly contains flaws, bugs, and design oversights. The API may change completely in the next commit. Use at your own risk — no surprises, except the ones we haven't found yet.

A lightweight, zero-allocation, high-performance FlatBuffers implementation in C# for game development. No heap allocations on the hot path, no reflection, no boxing. Types are source-generated from .fbs schemas.


Generated Types

See the FlatBuffers documentation for schema syntax. Every table generates a ref struct named {Name}Ref. Annotate with (plain_struct) to also generate a regular C# struct named {Name}.

The primary type is the ref struct. Plain structs exist for cases where you need to outlive the buffer.

Ref struct (PlayerRef) Plain struct (Player)
Heap allocation Zero Heap per string/vector/nested table
Additional storage None — reads/writes directly into the buffer Full copy of all fields
Buffer lifetime Must stay in scope Independent of buffer
Stack/field storage Stack only (ref struct rules) Anywhere — fields, lists, async
Mutability Setters write back into the buffer Regular mutable fields

Schema Support

Feature Status
namespace, table, struct, enum, union
root_type (multiple)
include / native_include
file_identifier ⚠️ Parsed; use builder.MarkRoot(pos, "ABCD"u8) manually
file_extension ❌ No effect
rpc_service ❌ Emits warning FBL003, no code gen
Field: deprecated, id, required, key, nested_flatbuffer, flexbuffer, force_align
Field: hash ❌ Parsed only
Type: plain_struct, original_order, force_align
Enum: bit_flags
All scalar types, vectors, nested types

Writing

Strings, vectors, and nested tables must be created before the table that references them.

Span<byte> buf = stackalloc byte[512];
var b = new FlatBufferBuilder(buf);

int name = b.CreateString("Alice"u8);
int inv  = b.CreateVector<int>(stackalloc int[] { 10, 20, 30 });

PlayerRef.Create(ref b, id: 42, name: name, hp: 250, inventory: inv);

ReadOnlySpan<byte> bytes = b.Finish();

Or set scalar and fixed-size struct fields individually after creation. All string, vector, and nested table values must still be created before calling Create — the reserve constructor immediately claims buffer space, so any CreateString/CreateVector call after it would be placed below the table's reserved region and cannot be referenced by it.

int name = b.CreateString("Alice"u8);  // must come first
var pb = PlayerRef.Create(ref b);
pb.Id = 42;          // scalar — fine
pb.Hp = 250;         // scalar — fine
// pb.Name = name;   // also fine, offset was created before Create()
ReadOnlySpan<byte> bytes = b.Finish();

Pre-allocating with GetMaxSize

Every generated table has GetMaxSize(...) to calculate an exact upper-bound buffer size. Pass 0 for dynamic fields you are not writing.

// Fixed-size only — no parameters needed
Span<byte> buf = stackalloc byte[PlayerRef.GetMaxSize()];

// With dynamic fields
int bufSize = PlayerRef.GetMaxSize(nameByteCount: 5, inventoryCount: 3);
Span<byte> buf = stackalloc byte[bufSize];
Parameter suffix Meaning
ByteCount UTF-8 bytes for a string field, or total for all strings in a string vector
Count Number of vector elements
MaxSize Max-size budget for a variable nested table, ref union payload, or all elements in a variable vector

Nested table sizes compose:

WeaponSize w1 = WeaponRef.GetMaxSize(nameByteCount: 5);
WeaponSize w2 = WeaponRef.GetMaxSize(nameByteCount: 4);

int bufSize = MonsterRef.GetMaxSize(
    nameByteCount: 6,
    weaponsCount: 2,
    weaponsMaxSize: new WeaponSize(w1.Value + w2.Value));

Reading

var player = PlayerRef.GetRootAs(bytes);

int   id        = player.Id;
short hp        = player.Hp;
FlatString name = player.Name;

ReadOnlySpan<int> inventory = player.Inventory.AsSpan;

For non-root types, use the buffer position returned by the constructor:

var score = ScoreRef.Create(ref b, value: 9_876_543_210L);
var read  = new ScoreRef(b.Buffer, score.BufferPos);

Vectors

  • Scalar vectors: .AsSpan for zero-copy access
  • Table vectors: indexed by [i]
  • String vectors: indexed by [i], returns FlatString with .AsBytes

Fields annotated with (key) generate a binary-search LookupByKey method:

var entry = entries.LookupByKey(targetId);
if (entry.IsValid) { /* found */ }

Unions

  • All struct/enum members → value-type union with TryGetValue
  • Contains table membersreadonly ref struct with TryGetAs{Member} methods
// Value union
var shape = PointOrSize.FromPoint(new Point { X = 1, Y = 2 });
if (shape.TryGetValue(out Point p)) { ... }

// Ref union
if (scene.Shape.TryGetAsCircle(out var circle)) { ... }

Plain Structs

Annotate a table with (plain_struct) to generate a regular C# struct with Serialize / Deserialize helpers. Strings and vector fields allocate on the heap.

table Player (plain_struct) {
  id: int;
  name: string;
  inventory: [int];
}
var player = new Player { Id = 42, Name = "Alice"u8.ToArray(), Inventory = new[] { 10, 20, 30 } };
Span<byte> buf = stackalloc byte[4096];
var b = new FlatBufferBuilder(buf);
Player.Serialize(ref b, in player);
var bytes = b.Finish();

var read = new Player();
Player.Deserialize(bytes, ref read);

Custom Collections

Annotate vector fields with (CustomCollection) to replace the default array fields with IFlatBufferCollection<T> or IFlatBufferPlainVector<T>. This lets you supply your own collection type — including pooled ones — which can eliminate per-deserialize allocations if your implementation supports it. Register factories before use:

FlatBufferCollections<int>.Create = capacity => new MyIntCollection(capacity);
FlatBufferPlainVectors<Item>.Create = capacity => new MyItemVector(capacity);

FlexBuffers

Schema-less values can be stored in [ubyte] (flexbuffer) fields. The source generator emits an XxxFlexBuffer accessor alongside the raw byte-vector accessor. Supported value kinds: null, bool, int, uint, float, string, blob, vector.

table Event {
  payload: [ubyte] (flexbuffer);
}
Span<byte> flexBuf = stackalloc byte[256];
var fb = new FlexBufferBuilder(flexBuf);
var values = fb.CreateVector(stackalloc FlexBufferValue[]
{
    FlexBufferValue.Int(42),
    fb.CreateString("spawn"u8),
    FlexBufferValue.Bool(true),
});
VectorOffset payload = builder.CreateVector<byte>(fb.Finish(values));
EventRef.Create(ref builder, payload: payload);

long first = EventRef.GetRootAs(bytes).PayloadFlexBuffer.AsVector[0].AsInt64;
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.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.

Version Downloads Last Updated
0.0.3 82 5/30/2026