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

OSCHINA-MIRROR/yomorun-yomo-codec

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

Y3 Codec: формат данных версии 202007

Обзор

Версия: Draft-01 (v202007). Данный протокол определяет формат кадров Y3 Codec.

Содержание

  • Цели проектирования
  • Условные обозначения
  • Формат TLV
    • Тег (Tag)
      • Базовый тип пакета (Primitive Packet)
      • Тип пакета узла (Node Packet)
    • Длина (Length)
    • Значение (Value)
    • Пример формата TLV
  • Базовые типы пакетов (Primitive Type System)
    • Строковый тип (String)
    • Двоичный тип (Binary)
    • Переменный целочисленный тип (pvarint)
    • Переменный тип с плавающей точкой (TODO)
    • Предложение: тип «срез» (Slice)

Цели проектирования

Y3 Codec — это кодировщик, работающий быстрее реального времени. Бинарный формат подходит для кодирования и декодирования, особенно в контексте потоковой обработки и случайного доступа. Оптимизирован для использования в QUIC Transport. В данном документе не рассматривается RPC, он не связан с подключением и описывает только структуру данных.

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

В этом документе используются пользовательские форматы для описания пакетов данных и фреймворков. Цель этих форматов — описать метод представления, а не определить конкретные элементы протокола. Этот документ определяет полную семантику и структуру.

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

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

Для одиночных полей используется следующий символ: x (A) обозначает длину x как A бит; x (A..B) — длина x может быть любой от A до B; x (?) = C — фиксированная длина x равна C; x (?) = C..D — значение x находится между C и D; [x (E)] — часть в квадратных скобках является опциональной; x (E) ... — x повторяется ноль или более раз, и каждый повтор имеет длину E.

Этот документ использует порядок байтов Big-Endian, поля начинаются с высокого бита каждого байта.

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

Example Structure {
  One-bit Field (1),
  7-bit Field with Fixed Value (7) = 61,
  Arbitrary-Length Field (..),
  Variable-Length Field (8..24),
  Field With Minimum Length (16..),
  Field With Maximum Length (..128),
  [Optional Field (64)],
  Repeated Field (8) ...,
}

Формат TLV

0        7
+--------+
| Tag    |
+--------+--------+--------+--------+
| Length                            |
+--------+--------+--------+--------+
| ...
+--------+--------+--------+--------+
| Value Payloads                    |
+--------+--------+--------+--------+
| ...
+--------+--------+--------+--------+

Базовый пакет (Base Packet):

Base Packet {
  Tag (8),
  Length (8) ...,
  Value (8) ...,
}

Tag {
  TypeFlag (1),
  ArrayFlag (1),
  SequenceID (6),
}

Тег (Tag)

Длина тега составляет фиксированные 8 бит (1 байт).

  1. Старший бит F (1000_0000) является флагом типа пакета (Packet Type). Y3 Codec имеет два типа пакетов: базовый тип пакета (PrimitivePacket) и тип пакета узла (NodePacket). Для базового типа пакета этот бит всегда равен 0. Для типа пакета узла этот бит всегда равен 1.
  2. Следующий старший бит A (0100_0000) является признаком массива. Когда этот бит равен 1, значение (Value) узла представляет собой тип «срез» (аналогично массиву в JSON).
  3. Оставшиеся младшие 6 бит представляют собой идентификатор последовательности (Sequence Bits), который используется для идентификации Sequence ID узла (аналогично ключам в структуре данных JSON).

Базовые типы

Представляют значения данных базовых типов.

Тип пакета узла

Содержит по крайней мере один тип пакета узла или базовый тип. Все дочерние узлы объединяются в соответствии с форматом TLV для формирования окончательного значения типа пакета узла.

Длина (Length)

Описывает длину в байтах значения (Value) пакета. Используется переменный целочисленный тип pvarint.

Значение (Value)

Хранит значение пакета. При декодировании указывается конкретный тип данных.

Пример формата TLV

Пример: если использовать Y3 для кодирования следующей структуры данных JSON:

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

Во-первых, определяется вся структура сообщения, подобно файлу .proto в ProtoBuffer:

Базовый тип пакета, Tag определяется как 0x01, представляющий «age», его значение — переменное целое число (pvarint).
Тип пакета узла, Tag определяется как 0x82, представляющий «summary», этот узел содержит два базовых типа пакета:
  Базовый тип пакета, Tag определяется как 0x03, представляющий «name», его значение является строкой (string).
  Базовый тип пакета, Tag определяется как 0x04, представляющий «create», его значение также является строкой (string).
  1. Используя Tag = 0x01, описывается key=age, его значение равно 2, используется переменный целочисленный (pvarint) тип.
  2. Используя Tag = 0x82, описывается key=summary, его значение необходимо вывести из последующих шагов.
  3. Используя Tag = 0x03, описывается key=name, его значение «CELLA», используется строковый (string) тип.
  4. Используя Tag = 0x04, описывается key=reate, его значение «Y3», также используется строковый (string) тип.

Порядок кодирования (порядковые номера обозначают порядок):

1️⃣ 0x01 -> Tag=0x01 описывает key="age", так как старший бит равен 0, это означает, что его значение относится к базовому типу пакета.
    3️⃣ 0x01 -> длина этого значения составляет 1 байт, поэтому следующий байт является конкретным содержимым значения.
      2️⃣ 0x05 -> является переменным целым числом (pvarint), 0x05 представляет число 5.
8️⃣ 0x82 -> Tag=0x82 описывает key="summary", так как старший бит равен 1, это указывает на то, что значение (Value) относится к типу пакета узла.
    7️⃣ 0x0B -> длина этого значения равна 11 байтам, поэтому следующие 11 байт являются конкретным содержимым значения.
      1️⃣ 0x03 -> Tag=0x03 описывает key="name", так как старший бит равен 0, это указывает на то, что его значение принадлежит базовому типу пакета.
        3️⃣ 0x05 -> длина этого значения составляет 5 байтов, поэтому следующие 5 байтов являются конкретным содержимым значения.
          2️⃣ 0x43 0x45 0x4C 0x4C 0x41 -> **Система примитивных типов**

Основана на базовых типах данных:
* строка (используется кодировка UTF-8);
* двоичные данные;
* pvarint — тип переменной длины, который описывает переменное целочисленное значение.

**pvarint**

Используется прямой порядок байтов. Старший бит C является битом продолжения, он равен 1, если следующий байт также является частью значения, и 0 в противном случае. Следующий за старшим бит S определяет тип числа: для знаковых целых чисел это бит знака, а для беззнаковых целых — информационный бит. Оставшиеся биты старшего байта используются как бит знака для знаковых чисел или игнорируются для беззнаковых.

Для знаковых целых:
pvarint = {
  Continuation Bit (1),
  Signed Bit (1),
  Payloads (6..),
}

Для беззнаковых:
pvarint Value = {
  Continuation Bit (1),
  Payloads (7..),
}

Пример использования pvarint

В качестве примера возьмём десятичное число 511 в типе i32 языка Rust. В двоичном представлении оно выглядит так: 0000 0000 0000 0000 0000 0001 1111 1111. Если использовать тип pvarint, то процесс кодирования будет состоять из четырёх шагов:
1. Эффективные данные: xxxx xxx0 1111 1111 (для обозначения каждого байта используется 8 бит, x обозначает игнорируемые биты; 511 — положительное число, поэтому его бит знака равен 0).
2. Все биты x заменяются битами знака 0: 0000 0001 1111 1111.
3. Поскольку старший бит используется для обозначения продолжения, эффективные данные имеют только 7 бит. Мы добавляем старший бит y к каждому байту: y000 0011 y111 1111.
4. Если есть ещё байты, старший бит следующего байта устанавливается в 1, иначе в 0. Таким образом, получаем: 1000 0011 0111 1111.
После кодирования Y3 для представления числа 511 требуется всего два байта.

Рассмотрим пример с отрицательным числом -1 в типе i32. Его двоичное представление: 1111 1111 1111 1111 1111 1111 1111 1111. Процесс кодирования с использованием pvarint состоит из следующих шагов:
1. Эффективные данные: xxxx xx11 (каждый байт имеет 8 бит; -1 — отрицательное число, поэтому бит знака равен 1).
2. Заменяем все биты x битами знака: 1111 1111.
3. Так как старший бит используется для продолжения, эффективные данные содержат только 7 битов. Добавляем старший бит y к каждому байту: y111 1111.
4. Поскольку больше нет байтов, старший бит устанавливается в 0, что даёт нам: 0111 1111.
Используя кодировку Y3, для представления -1 нужен только один байт.

Булевы значения можно описать с помощью типа pvarint: 1 означает True, 0 — False.

Тип float пока не реализован.

Slice

Для реализации Tag предлагается исключить старший бит массива, обозначающий тип элемента, и сделать Slice встроенным базовым типом данных, структура которого представляет собой повторяющуюся пару Length-Value.

Опубликовать ( 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