Skip to content

Latest commit

 

History

History
335 lines (254 loc) · 13.6 KB

spec-ru.md

File metadata and controls

335 lines (254 loc) · 13.6 KB

Спецификация Binn

Формат

Каждое значение хранится с 4 возможными параметрами:

[type][size][count][data]

Но большинство из них являются необязательными. Только параметр типа используется во всех из них. Вот список используемых параметров для базовых типов данных:

boolean, null:
[type]

int, float (хранение: byte, word, dword или qword):
[type][data]

string, blob:
[type][size][data]

list, object, map:
[type][size][count][data]

Каждый параметр может храниться с полиморфным размером:

Параметр Размер
[type] 1 или 2 байта
[size] 1 или 4 байта
[count] 1 или 4 байта
[data] n байт

[Type]

Каждое значение хранится, начиная с типа данных. Он может использовать 1 или 2 байта. Первый байт делится следующим образом:

 +-------- Тип хранения
 |  +----- Размер подтипа
 |  |  +-- Подтип
000 0 0000

Хранение

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

  • Нет дополнительных байтов
  • 1 байт
  • Word (2 байта, big endian)
  • Dword (4 байта, big endian)
  • Qword (8 байт, big endian)
  • String (UTF-8, с завершающим нулем)
  • Blob
  • Контейнер

И константы:

Хранение Биты Hex Dec
NOBYTES 000 0 0000 0x00 0
BYTE 001 0 0000 0x20 32
WORD 010 0 0000 0x40 64
DWORD 011 0 0000 0x60 96
QWORD 100 0 0000 0x80 128
STRING 101 0 0000 0xA0 160
BLOB 110 0 0000 0xC0 192
CONTAINER 111 0 0000 0xE0 224

Размер подтипа

Следующий бит сообщает, использует ли тип 1 или 2 байта.

Если бит равен 0, тип использует только 1 байт, и подтип имеет 4 бита (от 0 до 15)

 +-------- Тип хранения
 |  +----- Размер подтипа
 |  |  +-- Подтип
000 0 0000

Когда бит равен 1, для типа используется еще один байт, и подтип имеет 12 бит (до 4096)

 +-------- Тип хранения
 |  +----- Размер подтипа
 |  |
000 1 0000  0000 0000
      |  Подтип   |
      +-------------+

Подтип

Каждое хранилище может иметь до 4096 подтипов. Они содержат информацию о том, какое значение хранится в этом пространстве хранения.

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

Вот значения для базовых типов данных с выделенным подтипом:

Тип Хранение Биты Hex Dec
Null NOBYTES 0000 0000 0x00 0
True NOBYTES 0000 0001 0x01 1
False NOBYTES 0000 0010 0x02 2
UInt8 BYTE 0010 0000 0x20 32
Int8 BYTE 0010 0001 0x21 33
UInt16 WORD 0100 0000 0x40 64
Int16 WORD 0100 0001 0x41 65
UInt32 DWORD 0110 0000 0x60 96
Int32 DWORD 0110 0001 0x61 97
Float DWORD 0110 0010 0x62 98
UInt64 QWORD 1000 0000 0x80 128
Int64 QWORD 1000 0001 0x81 129
Double QWORD 1000 0010 0x82 130
Text STRING 1010 0000 0xA0 160
DateTime STRING 1010 0001 0xA1 161
Date STRING 1010 0010 0xA2 162
Time STRING 1010 0011 0xA3 163
DecimalStr STRING 1010 0100 0xA4 164
Blob BLOB 1100 0000 0xC0 192
List CONTAINER 1110 0000 0xE0 224
Map CONTAINER 1110 0001 0xE1 225
Object CONTAINER 1110 0010 0xE2 226

Пользовательские типы

Приложение может использовать другой тип DateTime и хранить значение в DWORD или QWORD.

Хранение = QWORD (0x80)
Подтип = 5 (0x05) [выберите любой неиспользуемый]

Тип DateTime = (0x80 | 0x05 => 0x85)

Приложение может отправлять HTML внутри структуры Binn и определить тип, отличный от обычного текста.

Хранение = STRING (0xA0)
Подтип = 9 (0x09) [выберите любой неиспользуемый]

Тип HTML = (0xA0 | 0x09 => 0xA9)

Если подтип больше 15, должен использоваться новый байт, и бит размера подтипа должен быть установлен:

Хранение = STRING (0xA000)
Размер подтипа = (0x0100)
Подтип = 21 (0x0015)

Тип HTML = (0xA000 | 0x1000 | 0x0015 => 0xB015)

Созданный параметр типа должен храниться в формате big-endian.

[Размер]

Этот параметр используется в строках, блобах и контейнерах. Он может иметь 1 или 4 байта.

Если первый бит размера равен 0, используется только 1 байт. Таким образом, когда размер данных составляет до 127 (0x7F) байт, параметр размера будет использовать только 1 байт.

В противном случае используется параметр размера 4 байта с msb 1. Это оставляет нам верхний предел в 2 гигабайта (0x7FFFFFFF).

Размер данных Использование параметра размера
<= 127 байт 1 байт
> 127 байт 4 байта

Нет проблемы, если маленький размер хранится с использованием 4 байт. Читатель должен принимать оба варианта.

Для строк параметр размера не включает нулевой символ-терминатор.

Для контейнеров параметр размера включает параметр типа. Он хранит размер всей структуры.

Примечание: в версиях до 2.0 размеры блобов хранятся только с 4 байтами и без поддержки размеров 1 байт.

[Количество]

Этот параметр используется только в контейнерах для информирования о количестве элементов внутри них. Он может иметь 1 или 4 байта, отформатированных точно так же, как параметр размера.

Количество Использование параметра количества
<= 127 элементов 1 байт
> 127 элементов 4 байта

Контейнеры

Список

Списки - это контейнеры, которые хранят значения одно за другим.

Параметр количества сообщает о количестве значений внутри контейнера.

[123, "test", 2.5, true]

Карта

Карты - это ассоциативные массивы с использованием целых чисел для ключей.

Ключи хранятся с использованием big-endian DWORD (4 байта), которые считываются как знаковые целые числа.

Таким образом, текущие пределы составляют от INT32_MIN до INT32_MAX. Но есть возможность увеличения, если это необходимо.

Параметр количества сообщает о количестве пар ключ/значение внутри контейнера.

{1: 10, 5: "the value", 7: true}

Объект

Объекты - это ассоциативные массивы с использованием текста для ключей.

Ключи не оканчиваются нулевым символом, и предел составляет 255 байт.

Ключи хранятся перед длиной ключа с использованием одного байта для этого.

Параметр количества сообщает о количестве пар ключ/значение внутри контейнера.

{"id": 1, "name": "John", "points": 30.5, "active": true}

Ограничения

Тип Мин Макс
Целые числа INT64_MIN UINT64_MAX
Числа с плавающей точкой IEEE 754
Строки 0 2 ГБ
Блобы 0 2 ГБ
Контейнеры 4 2 ГБ

Ассоциативные массивы

Тип ключа Мин Макс
Число INT32_MIN INT32_MAX
Текст 0 255 байт

Подтипы: до 4096 для каждого типа хранения

Примеры структур

Json-данные, такие как {"hello":"world"}, сериализуются как:

Binn: (17 байт)

  \xE2           // [тип] объект (контейнер)
  \x11           // [размер] общий размер контейнера
  \x01           // [количество] пар ключ/значение
  \x05hello      // ключ
  \xA0           // [тип] = строка
  \x05           // [размер]
  world\x00      // [данные] (с нулевым символом-терминатором)

Список из 3 целых чисел:

Json: (14 байт)

[123, -456, 789]

Binn: (11 байт)

  \xE0           // [тип] список (контейнер)
  \x0B           // [размер] общий размер контейнера
  \x03           // [количество] элементов
  \x20           // [тип] = uint8
  \x7B           // [данные] (123)
  \x41           // [тип] = int16
  \xFE\x38       // [данные] (-456)
  \x40           // [тип] = uint16
  \x03\x15       // [данные] (789)

Список внутри карты:

Json: (25 байт)

{1: "add", 2: [-12345, 6789]}

Binn: (26 байт)

 \xE1             // [тип] карта (контейнер)
 \x1A             // [размер] общий размер контейнера
 \x02             // [количество] пар ключ/значение
 \x00\x00\x00\x01 // ключ
 \xA0             // [тип] = строка
 \x03             // [размер]
 add\x00          // [данные] (с нулевым символом-терминатором)
 \x00\x00\x00\x02 // ключ
 \xE0             // [тип] список (контейнер)
 \x09             // [размер] общий размер контейнера
 \x02             // [количество] элементов
 \x41             // [тип] = int16
 \xCF\xC7         // [данные] (-12345)
 \x40             // [тип] = uint16
 \x1A\x85         // [данные] (6789)

Список объектов:

Json: (47 байт)

[ {"id": 1, "name": "John"}, {"id": 2, "name": "Eric"} ]

Binn: (43 байт)

 \xE0           // [тип] список (контейнер)
 \x2B           // [размер] общий размер контейнера
 \x02           // [количество] элементов

 \xE2           // [тип] объект (контейнер)
 \x14           // [размер] общий размер контейнера
 \x02           // [количество] пар ключ/значение

 \x02id         // ключ
 \x20           // [тип] = uint8
 \x01           // [данные] (1)

 \x04name       // ключ
 \xA0           // [тип] = строка
 \x04           // [размер]
 John\x00       // [данные] (с нулевым символом-терминатором)

 \xE2           // [тип] объект (контейнер)
 \x14           // [размер] общий размер контейнера
 \x02           // [количество] пар ключ/значение

 \x02id         // ключ
 \x20           // [тип] = uint8
 \x02           // [данные] (2)

 \x04name       // ключ
 \xA0           // [тип] = строка
 \x04           // [размер]
 Eric\x00       // [данные] (с нулевым символом-терминатором)