SimpleBinary - Легковесная замена protobuf/flatbuffers

SimpleBinary - попытка создать простейший бинарный сериализатор, обладающий следующими свойствами:

  • Легкая и простая в освоении схема описания данных.
  • Возможность поддержки нескольких языков.
  • Легковесность и отсутствие аллокаций в процессе работы.

Данный пакет является реализацией для C# и может использоваться в любом движке с его поддержкой,
позже будет добавлена поддержки других языков.

Схема данных

Кроссплатформенность и возможность версионирования формата данных обеспечивается генерацией кода по заранее описанной схеме.
Например, нужно описать инвентарь из предметов, имеющих идентификатор и количество:

1
2
3
4
5
6
7
8
; Описание элемент инвентаря.
[item]
id=u32 ; идентификатор, тип unsigned int 32bit
count=u32 ; количество, тип unsigned int 32bit

; Описание инвентаря
[inventory]
items=item[] ; элементы инвентаря, тип коллекция элементов [item].

В качестве простых типов поддерживаются 1-2-4-байтные знаковые и беззнаковые типы, 4-8-байтовые числа с плавающей запятой, а так же строки с ограниченной длиной (до 64к байт).
Так же поддерживаются перечисления и коллекции как из простых, так и из пользовательских типов. Все это обернуто в пулинг и
не вызывает новых аллокаций в процессе работы.

Конфигурация генератора

Для каждого языка есть набор настроек, позволяющих управлять генерацией конечного кода. Для C# это следующие пункты:

1
2
3
4
5
6
[cs]
namespace=Client.Serialization.V1
prefix=// Сгенерировано автоматически, руками править не рекомендуется.
enumName=SB_PacketType
outFile=generated.cs
threads=false

Тут можно указать:

  • пространство имен, в которое будет завернут код.
  • префикс-заголовок файла.
  • настроить имя перечисления для определения типа данных в дальнейшем.
  • путь до сгенерированного файла и настроить генерацию потокобезопасного варианта (медленнее, но позволяет использовать пулинг в нескольких потоках).

Генерация кода

Для кодогенерации в самом простом случае не требуется что-либо устанавливать - она работает локально в браузере, достаточно открыть html из пакета, подставить конфигурацию со схемой данных и нажать кнопку - готовый файл будет предложен к скачиванию.
Если хочется автоматизации, то она так же возможна через NodeJS из командной строки - достаточно будет указать пути до файлов настроек и все сгенерируется автоматически.

Использование в коде

Давайте сериализуем тестовый инвентарь с одним предметом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using Leopotam.SimpleBinary;

// Создаем тестовый набор данных.
Inventory inv = Inventory.New ();
Item item = Item.New ();
item.Id = 1;
item.Count = 2;
inv.Items.Add (item);
// Сериализуем их. Массив байт тут выполняет роль стартового
// буфера и может расширяться в процессе записи.
byte[] buf = new byte[1024];
SimpleBinaryWriter sbw = new SimpleBinaryWriter (buf);
inv.Serialize (ref sbw);
// Очищаем экземпляр после сериализации.
inv.Recycle();
// Получаем актуальный буфер с сериализованными данными.
(byte[] serializedData, int len) = sbw.GetBuffer ();

А теперь десериализуем обратно:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using Leopotam.SimpleBinary;

SimpleBinarReader sbr = new SimpleBinarReader (serializedData);
(Inventory inv2, bool ok) = Inventory.Deserialize (ref sbr);
if (!ok) {
// Некорректные данные (закончился поток байт, другой тип данных и т.п).
return;
}
// Работаем с полученными данными.
// inv2.Items[0].id == 1
// inv2.Items[0].count == 2

// Очищаем.
inv2.Recycle();
Актуальные версии пакетов доступны в закрытом telegram-сервере для vk/boosty-подписчиков.
Оформить подписку можно здесь: