Модуль msgpack
Модуль msgpack декодирует сырые строки MsgPack,
преобразуя их в объекты Lua, и кодирует объекты Lua, преобразуя их в
сырые строки MsgPack. Tarantool активно использует MsgPack внутри
системы, поскольку кортежи в Tarantool
хранятся в виде массивов MsgPack.
Кроме того, начиная с версии 2.10.0, с помощью модуля msgpack можно
создавать специальный объект Lua типа userdata — объект MsgPack.
Объект MsgPack хранит произвольные данные MsgPack и может быть создан из
любого объекта Lua, включая другой объект MsgPack, а
также из сырой строки MsgPack. У объекта
MsgPack есть собственный набор методов и
итераторов.
Ниже приведен список членов msgpack и связанных объектов.
Элементы
- msgpack.encode(lua_value) — преобразование объекта Lua в строку в формате MsgPack
- msgpack.encode(lua_value,ibuf) — преобразование объекта Lua в строку в формате MsgPack в ibuf
- msgpack.decode(msgpack_string) — преобразование строки в формате MsgPack в объект Lua
- msgpack.decode(C_style_string_pointer) — преобразование строки в формате MsgPack в ibuf в объект Lua
- msgpack.decode_unchecked(msgpack_string) — преобразование строки в формате MsgPack в объект Lua
- msgpack.decode_unchecked(C_style_string_pointer) — преобразование строки в формате MsgPack в объект Lua
- msgpack.decode_array_header(byte-array, size) —
вызов функции
mp_decode_arrayиз библиотеки MsgPuck и возврат размера массива и указателя на первый элемент массива - msgpack.decode_map_header(byte-array, size) —
вызов функции
mp_decode_mapиз библиотеки MsgPuck и возврат размера map и указателя на первый элемент map - Параметр __serialize — спецификация структуры вывода
- msgpack.cfg() — изменение параметров конфигурации MsgPack
- msgpack.NULL — аналог
nilв Lua - msgpack.object(lua_value) — создание объекта MsgPack из объекта Lua
- msgpack.object_from_raw(msgpack_string) — создание объекта MsgPack из строки в формате MsgPack
- msgpack.object_from_raw(C_style_string_pointer, size) — создание объекта MsgPack из строки в формате MsgPack
- msgpack.is_object(some_argument) — проверка, является ли аргумент объектом MsgPack
Связанные объекты
- msgpack_object — объект MsgPack
- iterator_object — объект-итератор MsgPack
Преобразует объект Lua в строку в формате MsgPack.
Параметры:
lua_value— скалярное значение или значение таблицы Lua.
Возвращает
исходное содержимое в формате строки MsgPack;
Тип возвращаемого значения
строка MsgPack
Преобразует объект Lua в строку MsgPack в ibuf — буфере, создаваемом
функцией buffer.ibuf(). Как и в случае с
msgpack.encode(lua_value), результат
представляет собой строку MsgPack, но записывается в выходной буфер
ibuf вместо возврата.
Параметры:
lua_value(lua-object) — скалярное значение или значение таблицы Lua.ibuf(buffer) — (выходной параметр) куда записывается результирующая строка MsgPack
Возвращает
количество байтов в выходных данных
Тип возвращаемого значения
строка MsgPack
Пример использования buffer.ibuf(), ffi.string() и string.hex():
ibuf = require('buffer').ibuf()msgpack_string_size = require('msgpack').encode({'a'}, ibuf)msgpack_string = require('ffi').string(ibuf.rpos, msgpack_string_size)string.hex(msgpack_string)
Результат: '91a161', так как 91 — это кодировка MessagePack для «fixarray size 1», a1 — кодировка MessagePack для «fixstr size 1», а 61 — кодировка UTF-8 символа 'a'.
Преобразует строку MsgPack в объект Lua.
Параметры:
msgpack_string(string) — строка MsgPack.start_position(integer) — позиция начала, минимум = 1, максимум = длина строки, по умолчанию = 1.
Возвращает
- (если
msgpack_string— корректная строка MsgPack) исходное содержимоеmsgpack_stringв формате объекта Lua, обычно таблицы Lua; (в противном случае) скалярное значение, например строка или число; - "next_start_position". Если
decodeостанавливается после разбора до байта N вmsgpack_string, то "next_start_position" будет равно N + 1, иdecode(msgpack_string, next_start_position)продолжит разбор с того места, где остановился предыдущий вызовdecode, плюс 1. Обычноdecodeразбирает всю строкуmsgpack_string, поэтому "next_start_position" будет равноstring.len(msgpack_string)+ 1.
Тип возвращаемого значения
объект Lua и число
Пример: результат: ['a'] и 4:
msgpack_string = require('msgpack').encode({'a'})require('msgpack').decode(msgpack_string, 1)
Преобразует строку MsgPack, адрес которой передан в виде указателя на
строку в стиле C (например, указателя rpos внутри ibuf, создаваемого
функцией buffer.ibuf()), в объект Lua. Указатель на
строку в стиле C может быть описан как cdata<char *> или
cdata<const char *>.
Параметры:
C_style_string_pointer(buffer) — указатель на строку MsgPack.size(integer) — количество байтов в строке MsgPack
Возвращает
- (если C_style_string_pointer указывает на корректную строку MsgPack)
исходное содержимое
msgpack_stringв формате объекта Lua, обычно таблицы Lua; (в противном случае) скалярное значение, например строка или число; - returned_pointer = указатель в стиле C на байт после переданных данных, так что C_style_string_pointer + size = returned_pointer
Тип возвращаемого значения
таблица и указатель в стиле C на позицию после переданных данных
Пример: пример использования buffer.ibuf и арифметики указателей. Результат: ['a'], 3 и true:
ibuf = require('buffer').ibuf()msgpack_string_size = require('msgpack').encode({'a'}, ibuf)a, b = require('msgpack').decode(ibuf.rpos, msgpack_string_size)a, b - ibuf.rpos, msgpack_string_size == b - ibuf.rpos
Входные и выходные данные те же, что и для msgpack.decode(string).
Входные и выходные данные те же, что и для
msgpack.decode(C_style_string_pointer),
за исключением того, что size не требуется. Часть проверок
пропускается, и decode_unchecked(C_style_string_pointer) может
работать с указателями на строки в буферах, которые
decode(C_style_string_pointer) не может обработать. Пример см. в
модуле buffer.
Вызывает функцию mp_decode_array из библиотеки
MsgPuck и возвращает размер
массива и указатель на первый элемент массива. Последующий вызов
msgpack_decode может декодировать отдельный элемент вместо всего
массива.
Параметры:
byte-array— указатель на строку MsgPack.size— число, большее или равное длине строки
Возвращает
- размер массива;
- указатель на позицию после заголовка массива.
Пример:
-- Example of decode_array_header-- Suppose we have the raw data '\x93\x01\x02\x03'.-- \x93 is MsgPack encoding for a header of a three-item array.-- We want to skip it and decode the next three items.msgpack = require('msgpack');ffi = require('ffi');x, y = msgpack.decode_array_header(ffi.cast('char*', '\x93\x01\x02\x03'), 4)a = msgpack.decode(y, 1);b = msgpack.decode(y + 1, 1);c = msgpack.decode(y + 2, 1);a, b, c-- The result is: 1,2,3.
Вызывает функцию mp_decode_map из библиотеки
MsgPuck и возвращает размер карты
и указатель на первый элемент карты. Последующий вызов msgpack_decode
может декодировать отдельный элемент вместо всей карты.
Параметры:
byte-array— указатель на строку MsgPack.size— число, большее или равное длине строки MsgPack
Возвращает
- размер карты;
- указатель на позицию после заголовка карты.
Пример:
-- Example of decode_map_header-- Suppose we have the raw data '\x81\xa2\x41\x41\xc3'.-- '\x81' is MsgPack encoding for a header of a one-item map.-- We want to skip it and decode the next map item.msgpack = require('msgpack');ffi = require('ffi')x, y = msgpack.decode_map_header(ffi.cast('char*', '\x81\xa2\x41\x41\xc3'), 5)a = msgpack.decode(y, 3);b = msgpack.decode(y + 3, 1)x, a, b-- The result is: 1,"AA", true.
Структура вывода MsgPack может быть задана с помощью параметра
__serialize:
- 'seq', 'sequence', 'array' — таблица кодируется как массив
- 'map', 'mapping' — таблица кодируется как карта
- function — метаметод, вызываемый для получения сериализуемого представления таблиц, объектов cdata или userdata
Сериализация 'A' и 'B' с разными значениями __serialize дает
разные результаты. Чтобы продемонстрировать это, ниже приведена
процедура, которая кодирует {'A','B'} и как массив, и как карту, а
затем отображает каждый результат в шестнадцатеричном формате.
function hexdump(bytes)local result = ''for i = 1, #bytes doresult = result .. string.format("%x", string.byte(bytes, i)) .. ' 'endreturn resultendmsgpack = require('msgpack')m1 = msgpack.encode(setmetatable({'A', 'B'}, {__serialize = "seq"}))m2 = msgpack.encode(setmetatable({'A', 'B'}, {__serialize = "map"}))print('array encoding: ', hexdump(m1))print('map encoding: ', hexdump(m2))
Результат:
array encoding: 92 a1 41 a1 42map encoding: 82 01 a1 41 02 a1 42
На странице спецификации MsgPack указано, что первая кодировка означает:
fixarray(2), fixstr(1), "A", fixstr(1), "B"
а значение второго результата кодирования:
fixmap(2), key(1), fixstr(1), "A", key(2), fixstr(2), "B"
Ниже приведены примеры всех стандартных типов: слева отображение в Lua-таблице, а справа – имя и кодировка в формате MsgPack.
{} | 'fixmap' = 80, если метатаблица 'map', иначе 'fixarray' = 90 |
|---|---|
'a' | 'fixstr' = a1 61 |
false | 'false' = c2 |
true | 'true' = c3 |
127 | 'positive fixint' = 7f |
65535 | 'uint 16' = cd ff ff |
4294967295 | 'uint 32' = ce ff ff ff ff |
nil | 'nil' = c0 |
msgpack.NULL | то же, что nil |
[0] = 5 | 'fixmap(1)' + 'positive fixint' (для ключа) + 'positive fixint' (для значения) = 81 00 05 |
[0] = nil | 'fixmap(0)' = 80 – nil не сохраняется, если это отсутствующее значение карты |
1.5 | 'float 64' = cb 3f f8 00 00 00 00 00 00 |
Изменяет параметры конфигурации MsgPack.
Все значения — целые числа или логические true/false.
Параметр | По умолчанию | Назначение |
|---|---|---|
| 128 | Максимальная глубина рекурсии при кодировании |
| false | Определяет, следует ли обрезать таблицы с уровнем вложенности выше
|
| true | Определяет, следует ли включить кодирование чисел NaN и Inf |
| true | Определяет, будет ли сериализатор следовать полю метатаблицы __serialize |
| false | Определяет, следует ли использовать |
| false | Определяет, следует ли использовать NULL для нераспознанных типов |
| true | Определяет, следует ли обрабатывать избыточно разреженные массивы как карты. Подробное описание см. ниже |
| 2 | 1/ |
| 10 | Ограничение, гарантирующее, что небольшие массивы Lua всегда кодируются как разреженные массивы (вместо генерации ошибки или кодирования в виде карты) |
| true | Определяет, как объекты ошибок
(box.error.new())
кодируются в формате MsgPack: если |
| true | Определяет, следует ли включить декодирование чисел NaN и Inf |
| true | Определяет, следует ли устанавливать метатаблицы для всех массивов и карт |
При кодировании кодировщик MsgPack пытается классифицировать таблицы по одному из четырех типов:
- map (карта) — хотя бы один индекс таблицы не является беззнаковым целым числом
- regular array (обычный массив) — все индексы массива доступны
- sparse array (разреженный массив) — хотя бы один индекс массива отсутствует
- excessively sparse array (избыточно разреженный массив) — количество пропущенных значений превышает заданное соотношение
Массив считается избыточно разреженным, если выполняются все следующие условия:
encode_sparse_ratio> 0max(table)>encode_sparse_safemax(table)>count(table)*encode_sparse_ratio
Кодировщик MsgPack никогда не считает массив избыточно разреженным при
encode_sparse_ratio = 0. Ограничение encode_sparse_safe гарантирует,
что небольшие массивы Lua всегда кодируются как разреженные массивы. По
умолчанию попытка кодирования избыточно разреженного массива вызывает
ошибку. Если параметр encode_sparse_convert установлен в значение
true, избыточно разреженные массивы обрабатываются как карты.
Пример 1 использования msgpack.cfg():
Если msgpack.cfg.encode_invalid_numbers = true (по умолчанию), то NaN
и Inf являются допустимыми значениями. Если это нежелательно, можно
запретить msgpack.encode() принимать их, задав
msgpack.cfg{encode_invalid_numbers = false}, таким образом:
tarantool> msgpack = require('msgpack'); msgpack.cfg{encode_invalid_numbers = true}---tarantool> msgpack.decode(msgpack.encode{1, 0 / 0, 1 / 0, false})---- [1, -nan, inf, false]- 22tarantool> msgpack.cfg{encode_invalid_numbers = false}---tarantool> msgpack.decode(msgpack.encode{1, 0 / 0, 1 / 0, false})---- error: ... number must not be NaN or Inf'
Пример 2: msgpack.cfg():
Чтобы избежать ошибок при попытках закодировать неизвестные типы данных как userdata/cdata, можно использовать следующий код:
tarantool> httpc = require('http.client').new()---tarantool> msgpack.encode(httpc.curl)---- error: unsupported Lua type 'userdata'tarantool> msgpack.cfg{encode_use_tostring = true}---tarantool> msgpack.encode(httpc.curl)---- !!binary tnVzZXJkYXRhOiAweDAxMDU5NDQ2Mzg=
Аналогичные параметры конфигурации существуют для JSON и YAML.
Значение, сопоставимое с нулевым значением "nil" в языке Lua, которое можно использовать в качестве объекта-заполнителя в кортеже.
Пример:
tarantool> msgpack = require('msgpack')---tarantool> y = msgpack.encode({'a',1,'b',2})---tarantool> z = msgpack.decode(y)---tarantool> z[1], z[2], z[3], z[4]---- a- 1- b- 2tarantool> box.space.tester:insert{20, msgpack.NULL, 20}---- [20, null, 20]
Начиная с: 2.10.0
Кодирует произвольный объект Lua в формат MsgPack.
Параметры:
lua_value(lua-object) — объект Lua любого типа.
Возвращает
закодированные данные MsgPack, инкапсулированные в объект MsgPack.
Тип возвращаемого значения
userdata
Пример:
local msgpack = require('msgpack')-- Create a MsgPack object from a Lua object of any typelocal mp_from_number = msgpack.object(123)local mp_from_string = msgpack.object('hello world')local mp_from_array = msgpack.object({ 10, 20, 30 })local mp_from_table = msgpack.object({ band_name = 'The Beatles', year = 1960 })local mp_from_tuple = msgpack.object(box.tuple.new{1, 'The Beatles', 1960})
Начиная с: 2.10.0
Создает объект MsgPack из сырой строки MsgPack.
Параметры:
msgpack_string(string) — сырая строка MsgPack.
Возвращает
объект MsgPack
Тип возвращаемого значения
userdata
Пример:
local msgpack = require('msgpack')-- Create a MsgPack object from a raw MsgPack stringlocal raw_mp_string = msgpack.encode({ 10, 20, 30 })local mp_from_mp_string = msgpack.object_from_raw(raw_mp_string)
Начиная с: 2.10.0
Создает объект MsgPack из сырой строки MsgPack. Адрес строки MsgPack
передается как указатель на строку в стиле C, например, как указатель
rpos внутри ibuf, создаваемого функцией
buffer.ibuf(). Указатель на строку в стиле C может быть
описан как cdata<char *> или cdata<const char *>.
Параметры:
C_style_string_pointer(buffer) — указатель на сырую строку MsgPack.size(integer) — количество байтов в сырой строке MsgPack.
Возвращает
объект MsgPack
Тип возвращаемого значения
userdata
Пример:
local msgpack = require('msgpack')-- Create a MsgPack object from a raw MsgPack string using bufferlocal buffer = require('buffer')local ibuf = buffer.ibuf()msgpack.encode({ 10, 20, 30 }, ibuf)local mp_from_mp_string_pt = msgpack.object_from_raw(ibuf.buf, ibuf:size())
Начиная с: 2.10.0
Проверяет, является ли переданный аргумент объектом MsgPack.
Параметры:
some_argument— любой аргумент.
Возвращает
true, если аргумент является объектом MsgPack; иначе false
Тип возвращаемого значения
boolean
Пример:
local msgpack = require('msgpack')local mp_from_string = msgpack.object('hello world')-- Check if the given argument is a MsgPack objectlocal mp_is_object = msgpack.is_object(mp_from_string) -- Returns truelocal string_is_object = msgpack.is_object('hello world') -- Returns false
Объект MsgPack, хранящий произвольные данные MsgPack. Чтобы создать объект MsgPack из объекта или строки Lua, используйте следующие методы:
Если объект MsgPack хранит массив, его можно вставить в спейс базы данных:
box.space.bands:insert(msgpack.object({1, 'The Beatles', 1960}))
Начиная с: 2.10.0
Декодирует данные MsgPack в объекте MsgPack.
Возвращает
объект Lua
Тип возвращаемого значения
объект Lua
Пример:
local msgpack = require('msgpack')local mp_from_number = msgpack.object(123)local mp_from_string = msgpack.object('hello world')-- Decode MsgPack datalocal mp_number_decoded = mp_from_number:decode() -- Returns 123local mp_string_decoded = mp_from_string:decode() -- Returns 'hello world'
Начиная с: 2.10.0
Создает итератор для данных MsgPack.
Возвращает
объект-итератор для данных MsgPack
Тип возвращаемого значения
userdata
Начиная с: 2.11.0
Получает элемент массива MsgPack по указанному ключу индекса. Для получения элемента массива также можно использовать метод msgpack_object:get(key).
Ключ индекса, используемый для получения элемента массива, может быть одним из следующих:
- если объект MsgPack является массивом,
key— целочисленное значение (начиная с 1), указывающее индекс элемента; - если объект MsgPack является ассоциативным массивом,
key— строковое значение, указывающее ключ элемента. В этом случае обратиться к элементу массива можно также с помощью точечной нотации (msgpack_object.<key>).
Если указанный ключ отсутствует в массиве, msgpack_object[key]
возвращает nil.
Пример:
local msgpack = require('msgpack')local mp_from_array = msgpack.object({ 10, 20, 30 })local mp_from_table = msgpack.object({ band_name = 'The Beatles', year = 1960 })local mp_from_tuple = msgpack.object(box.tuple.new{1, 'The Beatles', 1960})-- Get MsgPack data by the specified index or keylocal mp_array_get_by_index = mp_from_array[1] -- Returns 10local mp_table_get_by_key = mp_from_table['band_name'] -- Returns 'The Beatles'local mp_table_get_by_nonexistent_key = mp_from_table['rating'] -- Returns nillocal mp_tuple_get_by_index = mp_from_tuple[3] -- Returns 1960
Начиная с: 2.11.0
Получает элемент массива MsgPack по указанному ключу индекса. Для получения элемента массива также можно использовать индексную нотацию (msgpack_object[key]).
Параметры:
-
key(number/string) — ключ индекса, используемый для получения элемента массива, который может быть одним из следующих:- если объект MsgPack является массивом,
key— целочисленное значение (начиная с 1), указывающее индекс элемента; - если объект MsgPack является ассоциативным массивом,
key— строковое значение, указывающее ключ элемента.
- если объект MsgPack является массивом,
Возвращает
элемент массива MsgPack. Если указанный ключ отсутствует в массиве,
get возвращает nil.
Итератор по массиву MsgPack.
Начиная с: 2.10.0
Декодирует заголовок массива MsgPack под курсором итератора и сдвигает курсор. После вызова этой функции итератор указывает на первый элемент массива или на значение, следующее за массивом, если массив пуст.
Возвращает
количество элементов в массиве
Тип возвращаемого значения
number
Возможные ошибки: вызывает ошибку, если тип значения под курсором
итератора не MP_ARRAY.
Пример:
local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header() -- returns 4local first = mp_array_iterator:decode() -- returns 10local second = mp_array_iterator:decode() -- returns 20mp_array_iterator:skip() -- returns none, skips 30local fourth = mp_array_iterator:decode() -- returns 40
Начиная с: 2.10.0
Декодирует заголовок карты MsgPack под курсором итератора и сдвигает курсор. После вызова этой функции итератор указывает на первый ключ, хранящийся в карте, или на значение, следующее за картой, если карта пуста.
Возвращает
количество пар ключ-значение в карте
Тип возвращаемого значения
number
Возможные ошибки: вызывает ошибку, если тип значения под курсором
итератора не MP_MAP.
Пример:
local msgpack = require('msgpack')local mp_map = msgpack.object({ foo = 123 })local mp_map_iterator = mp_map:iterator()local size = mp_map_iterator:decode_map_header() -- returns 1local first = mp_map_iterator:decode() -- returns 'foo'local second = mp_map_iterator:decode() -- returns '123'
Начиная с: 2.10.0
Декодирует значение MsgPack под курсором итератора и сдвигает курсор.
Возвращает
объект Lua, соответствующий значению MsgPack
Тип возвращаемого значения
объект Lua
Возможные ошибки: вызывает ошибку Lua, если нет данных для декодирования.
Пример:
local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header() -- returns 4local first = mp_array_iterator:decode() -- returns 10local second = mp_array_iterator:decode() -- returns 20mp_array_iterator:skip() -- returns none, skips 30local fourth = mp_array_iterator:decode() -- returns 40
Начиная с: 2.10.0
Возвращает значение MsgPack под курсором итератора как объект MsgPack без декодирования и сдвигает курсор. Метод не копирует данные MsgPack. Вместо этого он берет ссылку на исходный объект.
Возможные ошибки: вызывает ошибку Lua, если нет данных для декодирования.
Пример:
local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header() -- returns 3local first = mp_array_iterator:decode() -- returns 10mp_array_iterator:skip() -- returns none, skips 20local mp_value_under_cursor = mp_array_iterator:take()local third = mp_value_under_cursor:decode() -- returns 30
Начиная с: 2.10.0
Копирует указанное количество значений MsgPack, начиная с позиции курсора итератора, в новый объект массива MsgPack и сдвигает курсор.
Параметры:
count(number) — количество значений MsgPack для копирования
Возвращает
новый объект MsgPack
Возможные ошибки: вызывает ошибку Lua, если недостаточно значений для декодирования. В этом случае позиция курсора итератора не изменяется.
Пример:
local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header() -- returns 4local first = mp_array_iterator:decode() -- returns 10local mp_array_new = mp_array_iterator:take_array(2)local mp_array_new_decoded = mp_array_new:decode() -- returns {20, 30}local fourth = mp_array_iterator:decode() -- returns 40
Начиная с: 2.10.0
Сдвигает курсор итератора, пропуская одно значение MsgPack под курсором. Ничего не возвращает.
Возможные ошибки: вызывает ошибку Lua, если нет данных для пропуска.
Пример:
local msgpack = require('msgpack')local mp_array = msgpack.object({ 10, 20, 30, 40 })local mp_array_iterator = mp_array:iterator()local size = mp_array_iterator:decode_array_header() -- returns 4local first = mp_array_iterator:decode() -- returns 10local second = mp_array_iterator:decode() -- returns 20mp_array_iterator:skip() -- returns none, skips 30local fourth = mp_array_iterator:decode() -- returns 40