Сжатие и двоичные данные
Все 7 методов PK для UTF-8, массивов байтов, ZLIB, GZIP и Protobuf с точными форматами входа и обратимыми примерами.
Объект PK предоставляет 7 методов для трёх разных задач: перевода текста в байты, сжатия текста и работы с сообщениями Protobuf. Здесь особенно важен точный вид данных: строка с массивом JSON, строка Base64 и обычный текст не взаимозаменяемы. Те же операции в выражениях in-Line описаны в .
Что выбрать
Текст ↔ массив байтов
stringToByteArray возвращает байты UTF-8 как строку с массивом JSON, а byteArrayToString читает такую строку обратно как UTF-8.
Сжатие своей строки
Выберите согласованную пару ZLIB или GZIP. Обе пары передают сжатые байты как Base64, но используют разные двоичные обёртки.
Обмен по описанию полей
protoBuf создаёт и разбирает сообщение по номерам и типам полей. Описание должно точно совпадать с договором другой стороны.
Только сменить запись байтов
Для перехода между Base64 и шестнадцатеричной строкой используйте методы из раздела .
Четыре представления данных
На примере слова Привет различие выглядит так:
Привет — шесть знаков. Чтобы получить байты, необходимо выбрать кодировку; методы этой страницы используют UTF-8.
D0 9F D1 80 D0 B8 D0 B2 D0 B5 D1 82 — двенадцать байтов, показанных в шестнадцатеричной записи.
[208,159,209,128,208,184,208,178,208,181,209,130] — те же байты как десятичные числа.
0J/RgNC40LLQtdGC — печатная запись тех же байтов. Base64 не сжимает и не защищает содержимое.
ZLIB и GZIP сначала получают байты UTF-8, сжимают их и только затем записывают результат в Base64. Protobuf строит байты по описанию полей, поэтому одного исходного текста ему недостаточно.
Строка JSON — не сам массив
Методы byteArrayToString и protoBuf передают данные через строку. Используйте JSON.stringify(...): вызов PK.byteArrayToString([104, 105]) нарушает договор, а PK.byteArrayToString(JSON.stringify([104, 105])) передаёт строку "[104,105]", которую ожидает исполнитель.
Вход сначала проходит обработку in-Line
Перед преобразованием каждый из семи методов раскрывает функции и переменные in-Line внутри входной строки. Такая строка не является непрозрачными данными: разметка in-Line в тексте, JSON или поле Protobuf будет выполнена раньше сжатия, кодирования или разбора. Порядок этой обработки описан в .
Текст и массив байтов
PK.stringToByteArray(input)
Принимает текст, кодирует его в UTF-8 и возвращает строку, содержащую массив десятичных чисел JSON. Каждое число обозначает один байт от 0 до 255.
Чтобы работать с числами как с массивом JavaScript, разберите результат явно:
Запись той же операции в in-Line показана в .
PK.byteArrayToString(input)
Принимает строку с массивом чисел JSON, преобразует числа в байты и читает полученный массив как UTF-8. Возвращает обычный текст.
Неверный JSON, значение вместо массива или нечисловой элемент вызывают исключение. Не передавайте дроби и числа вне диапазона байта: исполнитель не определяет для них надёжного результата.
Произвольный файл нельзя читать как текст
Случайные байты могут не образовывать допустимый UTF-8, поэтому обратное преобразование способно изменить данные. Для файла храните Base64 или шестнадцатеричную запись; byteArrayToString применяйте к результату stringToByteArray либо к заранее известным байтам UTF-8.
Запись той же операции в in-Line показана в .
Проверяемая пара
Пара обратима для текста: первый метод сам создаёт допустимый массив UTF-8, а второй читает его в той же кодировке.
ZLIB и GZIP
Все четыре метода выполняют цепочку текст → UTF-8 → сжатые байты → Base64 либо её обратный ход. Они сжимают текст, а не готовый массив байтов и не файл.
ZLIB
Поток содержит заголовок ZLIB, данные DEFLATE и контрольную сумму Adler-32. Передавайте его только стороне, которая ожидает именно эту обёртку.
GZIP
Поток содержит заголовок GZIP, данные DEFLATE и завершающую часть GZIP. Это один поток, а не архив с несколькими файлами и именами.
Пары нельзя смешивать
Результат ZLibCompress передавайте только в ZLibDecompress, а результат GZIPCompress — только в GZIPDecompress. Одинаковый способ сжатия DEFLATE внутри не делает обёртки взаимозаменяемыми.
Пустая строка на входе любого из четырёх методов сразу возвращает пустую строку. Это особое правило: результат не является Base64 сжатого пустого потока. При неверном Base64, чужой обёртке или повреждённых данных метод возвращает строку Error: <описание>, а не выбрасывает исключение.
У ошибки нет отдельного вида результата
Успешная распаковка также возвращает обычный текст, поэтому строка, которая сама начинается с Error: , неотличима по виду от сообщения об ошибке. Если это различие существенно, проверяйте восстановленный текст по собственному договору: например, разбирайте ожидаемый JSON и проверяйте обязательные поля.
PK.ZLibCompress(input)
Принимает текст, сжимает его потоком ZLIB и возвращает сжатые байты как однострочную Base64.
Точная Base64 может измениться при смене средства сжатия или его настроек. Устойчивой проверкой служит восстановленный текст, а не совпадение с образцом побайтно. Обе записи in-Line приведены в .
PK.ZLibDecompress(input)
Принимает Base64 с потоком ZLIB, распаковывает байты и возвращает текст UTF-8.
Устройство этого потока определено в .
Проверяемая пара ZLIB
PK.GZIPCompress(input)
Принимает текст, сжимает его потоком GZIP и возвращает сжатые байты как однострочную Base64.
Точную Base64 также не закрепляйте как ожидаемый результат: заголовок GZIP допускает служебные поля. Обе записи in-Line приведены в .
PK.GZIPDecompress(input)
Принимает Base64 с потоком GZIP, распаковывает байты и возвращает текст UTF-8.
Устройство потока определено в .
Проверяемая пара GZIP
PK.protoBuf(input)
Метод создаёт, разбирает или дополняет одно сообщение Protobuf по описанию полей. Он не читает файл .proto, не извлекает описание из двоичного сообщения и не угадывает типы: при каждом вызове нужно передать точные номера и типы нужных полей.
action | Что требуется | Что возвращается |
|---|---|---|
encode | message_type, field_mapping, field_values | Base64 нового сообщения |
decode | message_type, field_mapping, protobuf_base64 | строка с объектом JSON |
update | все четыре свойства выше | Base64 сообщения с добавленными значениями |
Значение action приводится к нижнему регистру, поэтому encode, ENCODE и Encode выбирают одно действие. Остальные имена свойств и имена полей должны совпадать точно.
Договор входной строки
Вызов принимает результат JSON.stringify(...), а не сам объект JavaScript:
Имя сообщения выбирает одноимённый объект внутри field_mapping. Само имя в двоичные данные не записывается.
Сначала содержит имена сообщений, затем имена полей. Для каждого поля обязательны свойства number и type.
Обязателен для encode и update. Ключ должен существовать в описании выбранного сообщения; отсутствующий ключ не записывается.
Обязательная непустая Base64 для decode и update. Она должна содержать ровно одно двоичное сообщение.
Для вложенного поля типа message описание содержит объект fields. Для enum описание содержит объект values, сопоставляющий имена перечисления с целыми числами. Свойство name внутри описания поля не используется: именем служит ключ объекта.
Запись той же операции в in-Line показана в .
Поддерживаемые типы
Знаковые целые числа. В field_values и разобранном результате представлены числами JSON.
Беззнаковые целые числа. Разобранный uint64 возвращается строкой, чтобы не переполнить знаковое целое программы.
Принимает true, false, 1 или 0. Другое числовое значение читается как false, поэтому используйте только четыре явных значения.
Числа с плавающей точкой одинарной и двойной точности. Вход и результат представлены числами JSON.
Обычная строка, которая записывается и читается как UTF-8.
Двоичное поле. Входное и разобранное значения представлены Base64, а не массивом чисел.
При создании принимает известное имя либо число. При разборе возвращает имя, если число найдено в values, иначе само число.
Вложенное сообщение с собственным объектом fields. Можно передать один объект или массив объектов для повторяющегося вложенного поля.
Полная пара: создать и разобрать
Для указанных значений packetBase64 равен CgZBcnRoYXMSB1Njb3VyZ2U=, а decodedJson содержит {"login":"Arthas","password":"Scourge"}. Имена полей в сообщение не входят: login и password восстанавливаются только по номерам из field_mapping.
Что делает update
update сначала разбирает известные поля исходного сообщения, затем добавляет записи из field_values и заново создаёт сообщение. Это не надёжная замена прежнего значения.
При последующем decode поле login станет массивом ['Arthas', 'Jaina'], потому что новая запись добавлена после прежней.
update теряет неизвестные поля
Поля, которых нет в field_mapping, пропускаются при разборе и не попадают в новый результат. Известное поле добавляется повторно вместо удаления прежнего. Не используйте update как обычную замену, если нужно сохранить неизвестные данные или получить единственное значение поля.
Границы и ошибки
- Номер поля должен совпадать с описанием другой стороны. Допустимы номера от
1до536870911, кроме зарезервированного промежутка19000–19999; исполнитель сам не проверяет всё это правило. - Поддерживаются одиннадцать типов, перечисленных выше. Названия
sint32,sint64,fixed32,fixed64,sfixed32иsfixed64во внутреннем исполнителе обработаны неполно или несовместимо, поэтому в публичный договор не входят. - Повторяющиеся известные поля при
decodeсобираются в массив. Приencodeмассив поддерживается только для вложенного типаmessage; массивы простых строк, чисел иbytesне принимаются. Упакованные повторяющиеся числа не поддерживаются. - Неизвестное поле при
decodeпропускается, а отсутствующее известное поле не дополняется значением по умолчанию. - Неверный JSON, отсутствующее обязательное свойство, неизвестное действие, неверный тип значения или повреждённая Base64 вызывают исключение. В отличие от методов сжатия,
protoBufне возвращает строкуError: ....
Двоичная запись номеров и типов полей объяснена в .
Сначала получите точное описание
Для внешней службы возьмите исходный файл .proto или её точное описание и перенесите номера и типы только нужных полей. AuthRequest на этой странице объясняет форму вызова, но не является общей схемой для чужого узла.