Skip to content

boyism80/flatbuffer-ex

Repository files navigation

FlatBufferEx

A powerful extension tool for Google FlatBuffers that simplifies schema parsing and code generation with enhanced features like nullable types, object pooling, and multi-language support.

Features

  • Nullable Type Support: Add nullable fields to your FlatBuffer schemas
  • Multiple Tables per File: Declare multiple tables in a single .fbs file
  • Object Pooling: Built-in FlatBufferBuilder object pooling for better performance
  • Multi-Language Support: Generate code for C++ and C#
  • Template-Based Generation: Uses Scriban templates for flexible code generation
  • Simplified API: No need to manually handle FlatBufferBuilder for serialization

Installation

Prerequisites

  • .NET 6.0 or later
  • FlatBuffers compiler (automatically downloaded in release mode)

Build from Source

git clone https://github.com/boyism80/flatbuffer-ex.git
cd flatbuffer-ex
dotnet build

Usage

Command Line Interface

dotnet run -- --path <schema-directory> --lang <languages> --output <output-directory>

Parameters:

  • --path or -p: Directory containing .fbs schema files
  • --lang or -l: Target languages (e.g., "c++|c#")
  • --output or -o: Output directory for generated code
  • --include or -i: Include directory path (optional)

Example

dotnet run -- --path ./schemas --lang "c#" --output ./generated

Schema Definition

Basic Schema

// db.fbs
namespace fb.protocol.db;

table Character {
    name: string;
    weapon_color: ubyte?;  // Nullable field
    armor_color: ubyte?;
    level: uint = 1;       // Default value
}

table Item {
    model: uint;
    durability: uint?;     // Nullable field
    custom_name: string?;
}

table Spell {
    id: uint;
    name: string;
}

Including Other Schemas

// db.response.fbs
include "db.fbs";
namespace fb.protocol.db.response;

table Login {
    character: fb.protocol.db.Character;
    items: [fb.protocol.db.Item];      // Array of items
    spells: [fb.protocol.db.Spell];
}

Generated Code Usage

C# Example

using fb.protocol.db;
using System.Diagnostics;

var response = new fb.protocol.db.response.Login
{ 
    Character = new Character
    { 
        Name = "character",
        WeaponColor = null,
        ArmorColor = 1,
    },
    Items = new List<Item>
    { 
        new Item
        { 
            Model = 1,
            Durability = null
        },
        new Item
        { 
            Model = 2,
            Durability = 100
        }
    }
};

var bytes = response.Serialize();
var deserialized = fb.protocol.db.response.Login.Deserialize(bytes);

Debug.Assert(deserialized.Character.Name == "character");
Debug.Assert(deserialized.Character.WeaponColor == null);
Debug.Assert(deserialized.Character.ArmorColor == 1);

Debug.Assert(deserialized.Items.Count == 2);
Debug.Assert(deserialized.Items[0].Model == 1);
Debug.Assert(deserialized.Items[0].Durability == null);
Debug.Assert(deserialized.Items[1].Model == 2);
Debug.Assert(deserialized.Items[1].Durability == 100);

Debug.Assert(deserialized.Spells.Count == 0);

C++ Example

#include <protocol.h> // Generated header file

int main(int argc, const char** argv)
{
    auto character = fb::protocol::db::Character{};
    character.name = "character";
    character.weapon_color = std::nullopt;
    character.armor_color = 1;

    auto item1 = fb::protocol::db::Item{};
    item1.model = 1;
    item1.durability = std::nullopt;

    auto item2 = fb::protocol::db::Item{};
    item2.model = 2;
    item2.durability = 100;

    auto response = fb::protocol::db::response::Login
    {
        character,
        { item1, item2 }, 
        {}
    };

    auto bytes = response.Serialize();
    auto deserialized = fb::protocol::db::response::Login::Deserialize(bytes.data());

    assert(deserialized.character.name == "character");
    assert(deserialized.character.weapon_color == std::nullopt);
    assert(deserialized.character.armor_color == 1);

    assert(deserialized.items.size() == 2);
    assert(deserialized.items[0].model == 1);
    assert(deserialized.items[0].durability == std::nullopt);
    assert(deserialized.items[1].model == 2);
    assert(deserialized.items[1].durability == 100);

    assert(deserialized.spells.size() == 0);

    return 0;
}

Performance Features

Object Pooling (C#)

FlatBufferEx automatically uses object pooling for FlatBufferBuilder instances to reduce garbage collection pressure:

// Object pooling is handled automatically in Serialize() method
var bytes = myObject.Serialize(); // Uses pooled FlatBufferBuilder

The pool configuration:

  • Initial buffer size: 4KB
  • Maximum retained objects: 256
  • Thread-safe implementation

Architecture

Core Components

  • Parser: Parses .fbs schema files and extracts structure information
  • Services: Service-based architecture with dependency injection
    • IFileService: File system operations abstraction
    • ITemplateService: Template rendering operations
    • IFlatBufferCompilerService: FlatBuffer compiler management
    • ICodeGenerationService: Code generation orchestration
  • Model: Represents parsed schema elements (tables, fields, enums)
  • Configuration: Centralized configuration management with validation
  • Templates: Scriban templates for code generation

Service Architecture

FlatBufferEx uses a service-based architecture with dependency injection:

  • Separation of Concerns: Each service handles a specific responsibility
  • Testability: Services can be easily mocked for unit testing
  • Maintainability: Clear interfaces make the code easier to understand and modify
  • Error Handling: Centralized error handling with detailed error messages

Template System

FlatBufferEx uses Scriban templates for flexible code generation:

  • Template/c#.txt: C# code generation template
  • Template/cpp.txt: C++ code generation template
  • Template/raw.table.txt: Raw table generation template
  • Template/raw.enum.txt: Raw enum generation template

Supported Types

Primitive Types

  • byte, ubyte, bool
  • short, ushort, int, uint
  • long, ulong, float, double
  • string

Complex Types

  • Arrays: [type] (e.g., [int], [string])
  • Nullable: type? (e.g., int?, string?)
  • Custom Tables: References to other tables
  • Enums: Custom enumeration types

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Related Projects

This tool is used in the fb 2D MMORPG game server project.

About

FlatBuffers extension & code generator

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages