1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/yomorun-yomo-codec

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
draft-01.md 13 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 01.12.2024 03:17 36cfcd2

Y3 Codec: базовый формат (инварианты)

Обзор

Версия Draft-01 (v202007). Данный протокол определяет форматы отдельных сообщений.

Содержание

  • Формат пакета Y3-кодека (#Y3-Codec-Packet-Format)
  • Условные обозначения (#Notational-Conventions)
  • Формат TLV (#TLV-Format)
    • Тег (#Tag)
      • NodePacket (#NodePacket)
      • PrimitivePacket (#PrimitivePacket)
    • Длина (#Length)
    • Значение (#Value)
    • Пример формата TLV (#TLV-Example)
  • Система типов (#Type-System)
    • PVarUInt32 (#PVarInt)
    • Пример PVarUInt32 (#PvarInt-Example)

Формат пакета Y3-кодека

Определяет форматы сообщений.

  • Кодек быстрее реального времени.
  • Двоичный код подходит для кодирования/декодирования, особенно для произвольного доступа к потоковой обработке.
  • Предназначен для QUIC Transport.
  • Не связан с протоколом соединения, только формат сообщения.

Условные обозначения

Диаграммы пакетов и фреймов в этом документе используют специальный формат. Цель этого формата — обобщить, а не определить элементы протокола. Прозой определяются полные семантика и детали структур.

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

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

x (A): указывает, что x имеет длину A бит;

x (i): указывает, что x использует переменную длину кодирования в integer-encoding;

x (A..B): указывает, что x может иметь любую длину от A до B; A можно опустить, чтобы указать минимум ноль бит, и B можно опустить, чтобы не устанавливать верхний предел; значения в этом формате всегда заканчиваются на границе октета;

x (?) = C: указывает, что x имеет фиксированное значение C;

x (?) = C..D: указывает, что значение x находится в диапазоне от C до D включительно;

[x (E)]: указывает, что x является необязательным (и имеет длину E);

x (E)...: указывает, что x повторяется ноль или более раз (и каждый экземпляр имеет длину E).

В этом документе используются значения сетевого байтового порядка (то есть с прямым порядком байтов). Поля размещаются, начиная с старших битов каждого байта.

По соглашению отдельные поля ссылаются на сложное поле, используя имя сложного поля.

Например:

Пример структуры {
  Однобитовое поле (1),
  7-битное поле с фиксированным значением (7) = 61,
  Поле с переменной длиной целого числа (i),
  Произвольное поле (..),
  Переменное поле (8..24),
  Поле минимальной длины (16..),
  Поле максимальной длины (..128),
  [Необязательное поле (64)],
  Повторяющееся поле (8) ...,
}

Формат TLV

0        7
+--------+
| Тег    |
+--------+--------+--------+--------+
| Длина (PVarUInt32)               |
+--------+--------+--------+--------+
| ...
+--------+--------+--------+--------+
| Полезная нагрузка значений                    |
+--------+--------+--------+--------+
| ...
+--------+--------+--------+--------+
Базовый пакет {
  Тег (8),
  Длина (8..),
  Значение (8) ...,
}

Тег {
  Тип флага (1),
  Флаг массива (1),
  Идентификатор последовательности (6),
}

Тег

Фиксированная длина 8 бит (1 байт):

8   7   6                0
+------------------------+
| F | A |     SeqID      |
+------------------------+
  1. Самый старший бит F (1000_0000) — это флаг типа пакета, у Y3 Codec есть два типа пакетов: PrimitivePacket и NodePacket. Для PrimitivePacket этот бит всегда равен 0; для NodePacket этот бит всегда равен 1.
  2. Следующий старший бит A (0100_0000) является флагом массива, когда этот бит равен 1, это означает, что значение узла представляет собой тип Slice (аналогично массиву в структуре данных JSON).
  3. Оставшиеся младшие 6 бит представляют собой идентификатор последовательности битов Sequence Bits, который используется для представления идентификатора SeqID данного узла (аналогично роли ключа в структуре данных JSON). (Для одного NodePacket его подузлы могут иметь максимум 2^6=64).

Длина

Длина описывает длину байтов значения данного пакета, которая является переменной длиной PVarUInt32.

Значение

Значение хранит значение данного пакета. При декодировании пользователь должен указать конкретный тип данных для его декодирования.

Основные типы

Означает, что его значение является базовым типом данных.

Тип узла

Означает, что его значение содержит по крайней мере один NodePacket или PrimitivePacket, поэтому дочерние узлы объединяются в окончательный Value данного NodePacket в соответствии с кодировкой TLV.

Пример TLV

Если мы хотим преобразовать этот объект формата JSON в Y3:

{
    "age" : 5,
    "summary": {
      "name": "CELLA",
      "create": "Y3"
    }
}

Сначала определите структуру сообщения, как это делает файл .proto:


Primitive Packet, Tag=0x01 -> "age", тип значения pvarint.
Node Packet, Tag=0x82 -> "summary", этот узел содержит два примитивных пакета:
  Primitive Packet, Tag=0x03 -> "name", тип значения string.
  Primitive Packet, Tag=0x04 -> "create", тип значения string. 

**Использование:**
1. Используйте `Tag = 0x01`, чтобы описать `age`, его значение — целое число `2`, используйте тип `pvarint` при кодировании.
2. Используйте `Tag = 0x82`, чтобы описать `summary`, его полезная нагрузка требует анализа.
3. Используйте `Tag = 0x03`, чтобы описать `name`, его значение — строка `CELLA`.
4. Используйте `Tag = 0x04`, чтобы описать `create`, его значение — строка `Y3`.

**Кодирование:**

0x01 -> Tag=0x01 означает ключ="age" примитивный пакет. 0x01 -> Длина значения равна 1 (тип pvarint, 0x01=1, означает, что следующий 1 байт является полезной нагрузкой значения). 0x05 -> 0x05 — это тип pvarint, который представляет целое число 5. 0x82 -> Tag=0x82 означает ключ="summary" узловой пакет. 0x0B -> Длина значения составляет 11 (тип pvarint, 0x0B=11, означает, что следующие 11 байтов являются полезной нагрузкой значения). 0x03 -> Tag=0x03 означает ключ="name" примитивный пакет. 0x05 -> Длина значения равна 5 (тип pvarint, 0x05=5, означает, что следующие 5 байтов являются полезной нагрузкой значения). 0x43 0x45 0x4C 0x4C 0x41 -> UTF-8 строка для "CELLA". 0x04 -> Tag=0x04 означает ключ="create" примитивный пакет. 0x02 -> Длина значения равна 2 (тип pvarint, 0x02=2, означает, что следующими 2 байтами являются полезная нагрузка значения). 0x59 0x33 -> UTF-8 строка для "Y3".

Будет закодировано как:
`0x01 0x01 0x05 0x82 0x0B 0x03 0x05 0x43 0x45 0x4C 0x4C 0x41 0x04 0x02 0x59 0x33`

## Система типов ##

Поддерживаются следующие типы данных:

1. String.
1. Binary.
1. Boolean.
1. PVarInt32.
1. PVarUInt32.
1. PVarInt64.
1. PVarUInt64.
1. VarFloat32.
1. VarFloat64.

### String

UTF-8 строка.

### Binary

Сырые байты.

### Pvarint

`P-var-int` представляет собой переменную длину целого числа:
* «P» — для «заполнения знакового бита».
* «var» — для переменной длины.
* «int» — для целого числа.

8 7 6 0 +---+---+----------------+ | C |(S)| payloads | +---+---+----------------+


* Big-Endian.
* C `0x80` представляет `Continuation Bit`, если этот бит равен `1`, значит, следующий байт необходимо прочитать следующим, если этот бит равен `0`, значит, это последний байт значения.
* (S) `0x40` представляет как `Signed Bit` для Signed-Integer. для Unsigned-Integer это бит данных.
* С битом знака совпадают непрерывные старшие биты, остальные биты заполняются битом знака.

~~~
PVarInt32 Value {
  Continuation Bit (1),
  Signed Bit (1),
  Payloads (6..),
}

PVarUInt32 Value {
  Continuation Bit (1),
  Payloads (7..),
}
~~~

#### Пример Pvarint

Значение `i32` `511` в десятичной системе представлено в двоичном виде как `0000 0000 0000 0000 0000 0001 1111 1111`, оно использует 4 байта. Когда мы кодируем его в Pvarint, есть 4 шага:
1. Действительные байты: `xxxx xxx0 1111 1111`.
2. Заполнение всех `x` как знаковый бит `0`: `0000 0001 1111 1111`.
3. Выбор 7-битов в качестве битов значения: `y000 0011 y111 1111`.
4. Изменение MSB как `1`, кроме последнего байта: `1000 0011 0111 1111`.

Значение `i32` `-1` в десятичной системе представлено в двоичном виде как `1111 1111 1111 1111 1111 1111 1111 1111`, оно использует 4 байта. Когда мы кодируем его в Pvarint, есть 4 шага:
1. Действительные байты: `xxxx xx11`.
2. Заполнение всех `x` как знаковый бит `1`: `1111 1111`.
3. Выбор 7-битов в качестве битов значения: `y111 1111`.
4. Изменение MSB как `1`, кроме последнего байта: `0111 1111`.

### Boolean

Значение типа `PVarUInt32` представляет `0` или `1` в 1 байте.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/yomorun-yomo-codec.git
git@api.gitlife.ru:oschina-mirror/yomorun-yomo-codec.git
oschina-mirror
yomorun-yomo-codec
yomorun-yomo-codec
draft-01