Каждое значение хранится с 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 байт |
Каждое значение хранится, начиная с типа данных. Он может использовать 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 для каждого типа хранения
Binn: (17 байт)
\xE2 // [тип] объект (контейнер) \x11 // [размер] общий размер контейнера \x01 // [количество] пар ключ/значение \x05hello // ключ \xA0 // [тип] = строка \x05 // [размер] world\x00 // [данные] (с нулевым символом-терминатором)
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 // [данные] (с нулевым символом-терминатором)