Marshal Формат
Формат Marshal используется для сериализации объектов Ruby. Формат может хранить произвольные объекты с помощью трёх механизмов пользовательских расширений.
Для получения документации по использованию Marshal для сериализации и десериализации объектов, см. модуль Marshal.
В этом документе сериализованный набор объектов называется потоком. Реализация Ruby может загрузить набор объектов из String, IO или объекта, реализующего метод getc.
Формат потока
Первые два байта потока содержат мажорную и минорную версии, каждая как однобайтовое кодирование цифры. Реализация Ruby использует версию 4.8 (хранится как «x04x08») и поддерживается ruby 1.8.0 и новее.
Разные мажорные версии формата Marshal несовместимы и не могут быть поняты другими мажорными версиями. Меньшие минорные версии формата могут быть поняты более новыми минорными версиями. Формат 4.7 может быть загружен реализацией 4.8, но формат 4.8 не может быть загружен реализацией 4.7.
После байтов версии следует поток, описывающий сериализованный объект. Поток содержит вложенные объекты (такие же, как объект Ruby), но объекты в потоке не обязательно имеют непосредственное отображение на модель объекта Ruby.
Каждый объект в потоке описывается байтом, указывающим его тип, за которым следуют один или несколько байтов, описывающих объект. Когда ниже упоминается «объект», это означает любой из следующих типов, определяющих объект Ruby.
true, false, nil
Эти объекты имеют длину в один байт. «T» представляет true, «F» представляет false, а «0» представляет nil.
Fixnum и long
«i» представляет целое 32-битное со знаком, использующее упакованный формат. За типом следуют от одного до пяти байтов. Загруженное значение всегда будет Fixnum. На 32-битных платформах (где точность Fixnum меньше 32 бит) загрузка больших значений приведёт к переполнению в CRuby.
Тип fixnum используется для представления как объектов ruby Fixnum, так и размеров сериализованных массивов, хешей, переменных экземпляра и других типов. В следующих разделах «long» будет означать формат, описанный ниже, который поддерживает полную 32-битную точность.
Первый байт имеет следующие специальные значения:
- “x00”
-
Значение целого числа равно 0. Следующих байтов нет.
- “x01”
-
Общий размер целого числа равен двум байтам. Следующий байт — положительное целое число в диапазоне от 0 до 255. Только значения между 123 и 255 должны представляться таким образом для экономии байтов.
- “xff”
-
Общий размер целого числа равен двум байтам. Следующий байт — отрицательное целое число в диапазоне от -1 до -256.
- “x02”
-
Общий размер целого числа равен трём байтам. Следующие два байта — положительное целое число в формате little-endian.
- “xfe”
-
Общий размер целого числа равен трём байтам. Следующие два байта — отрицательное целое число в формате little-endian.
- “x03”
-
Общий размер целого числа равен четырём байтам. Следующие три байта — положительное целое число в формате little-endian.
- “xfd”
-
Общий размер целого числа равен четырём байтам. Следующие три байта — отрицательное целое число в формате little-endian.
- “x04”
-
Общий размер целого числа равен пяти байтам. Следующие четыре байта — положительное целое число в формате little-endian. Для совместимости с 32-битным ruby, только Fixnums меньше 1073741824 должны представляться таким образом. Для размеров потоковых объектов может использоваться полная точность.
- “xfc”
-
Общий размер целого числа равен двум байтам. Следующие четыре байта — отрицательное целое число в формате little-endian. Для совместимости с 32-битным ruby, только Fixnums больше -10737341824 должны представляться таким образом. Для размеров потоковых объектов может использоваться полная точность.
В противном случае первый байт — это значение с расширением знака восьми битов со смещением. Если значение положительное, значение определяется вычитанием 5 из значения. Если значение отрицательное, значение определяется добавлением 5 к значению.
Для многих значений существует несколько представлений. CRuby всегда выводит кратчайшее возможное представление.
Символы и последовательность байтов
«:” представляет реальный символ. Реальный символ содержит данные, необходимые для определения символа для остальной части потока, так как будущие появления в потоке вместо этого будут ссылками (ссылка на символ) на этот. Ссылка — это значение 32-битного числа с индексом ноль (так что первое вхождение :hello равно 0).
За байтом типа следует последовательность байтов, которая состоит из целого числа, указывающего количество байтов в последовательности, за которым следует столько байтов данных. Последовательности байтов не имеют кодировки.
Например, следующий поток содержит символ Symbol :hello:
"\x04\x08:\x0ahello"
«;” представляет ссылку на Symbol, которая ссылается на ранее определённый Symbol. За байтом типа следует целое число, содержащее индекс в таблице поиска для связанного (ссылочного) Symbol.
Например, следующий поток содержит [:hello, :hello]:
"\x04\b[\a:\nhello;\x00"
Когда ниже упоминается «символ», это может быть либо реальный символ, либо ссылка на символ.
Ссылки на Object
Отдельно от, но подобно ссылкам на символы, поток содержит только одну копию каждого объекта (как определяется object_id) для всех объектов, за исключением true, false, nil, Fixnum и Symbol (которые хранятся отдельно, как описано выше). Будет храниться одноиндексное 32-битное значение и повторно использоваться при повторной встрече объекта. (Первый объект имеет индекс 1).
«@» представляет ссылку на объект. За байтом типа следует целое число, указывающее индекс объекта.
Например, следующий поток содержит массив Array того же объекта "hello" дважды:
"\004\b[\a\"\nhello@\006"
Переменные экземпляра
«I» указывает, что переменные экземпляра следуют за следующим объектом. За байтом типа следует объект. За объектом следует длина, указывающая количество переменных экземпляра для объекта. За длиной следует набор пар имя-значение. Имена являются символами, а значения — объектами. Символы должны быть именами переменных экземпляра (:@name).
Объект Object («o» тип, описанный ниже) использует тот же формат для своих переменных экземпляра, что и описано здесь.
Для String и Regexp (описанные ниже) используется специальная переменная экземпляра :E, чтобы указать Encoding.
Расширенный
«e» указывает, что следующий объект расширен модулем. За байтом типа следует объект. За объектом следует символ, содержащий имя модуля, которым расширен объект.
Массив Array
«[» представляет собой Array. За байтом типа следует целое число, указывающее количество объектов в массиве. За длиной следуют указанные объекты.
Bignum
«l» представляет Bignum, который состоит из трёх частей:
- знак
-
Один байт, содержащий «+» для положительного значения или «-» для отрицательного.
- длина
-
Целое число, указывающее количество байтов данных Bignum, которые следуют за ним, разделённое на два. Умножьте длину на два, чтобы определить количество байтов данных, которые следуют за ним.
- данные
-
Байты данных Bignum, представляющие число.
Следующий код Ruby позволит восстановить значение Bignum из массива байтов:
result = 0 bytes.each_with_index do |byte, exp| result += (byte * 2 ** (exp * 8)) end
Class и Module
«c» представляет собой объект Class, «m» представляет собой Module, а «M» представляет собой либо класс, либо модуль (это старая форма для совместимости). Содержимое класса или модуля не включается, этот тип — только ссылка.
Переменные экземпляра не допускаются для класса или модуля.
Если класс или модуль не существует, должно быть выброшено исключение.
Для типов «c» и «m» загруженный объект должен быть классом или модулем соответственно.
Данные
«d» представляет объект Data. (Объекты Data — это обернутые указатели из расширений Ruby.) За байтом типа следует символ, указывающий класс для объекта Data, и объект, содержащий состояние объекта Data.
Для сохранения объекта Data Ruby вызывает _dump_data. Для загрузки объекта Data Ruby вызывает _load_data с состоянием объекта на вновь выделенном экземпляре.
Float
«f» представляет объект Float. За байтом типа следует последовательность байтов, содержащая значение с плавающей запятой. Следующие значения являются специальными:
- “inf”
-
Положительная бесконечность
- “-inf”
-
Отрицательная бесконечность
- “nan”
-
Не число
В противном случае последовательность байтов содержит C double (загружаемый с помощью strtod(3)). Более старые минорные версии Marshal также хранили дополнительные биты мантиссы для обеспечения переносимости между платформами, но 4.8 не включает их. См.
- ruby-talk:69518
-
для некоторого объяснения.
Hash и Hash со значением по умолчанию
«{» представляет объект Hash, а «}» представляет Hash с установленным значением по умолчанию (Hash.new 0). За байтом типа следует целое число, указывающее количество пар ключ-значение в Hash, размер. За размером следуют удвоенное количество объектов.
Для Hash со значением по умолчанию, значение по умолчанию следует за всеми парами.
Module и старый Module
Object
«o» представляет собой объект, у которого нет другой специальной формы (например, пользовательского или встроенного формата). За байтом типа следует символ, содержащий имя класса объекта. За именем класса следует целое число, указывающее количество имён и значений переменных экземпляра для объекта. За размером следуют удвоенное количество пар объектов.
Ключи в парах должны быть символами, содержащими имена переменных экземпляра.
Регулярное выражение
“/” обозначает регулярное выражение. После байта типа следует последовательность байтов, содержащая исходный код регулярного выражения. После байта типа следует байт, содержащий опции регулярного выражения (регистронезависимое и т.д.) в виде знакового 8-битного значения.
Регулярные выражения могут иметь кодировку, прикреплённую через переменные экземпляра (см. выше). Если кодировка не прикреплена, необходимо удалить эскейпы для следующих спецсимволов regexp, отсутствующих в ruby 1.8: g-m, o-q, u, y, E, F, H-L, N-V, X, Y.
String
'“' обозначает String. После байта типа следует последовательность байтов, содержащая содержимое строки. При выгрузке из ruby 1.9 должна быть включена переменная экземпляра кодировки (:E см. выше), за исключением случаев, когда кодировка — бинарная.
Struct
“S” обозначает Struct. После байта типа следует символ, содержащий имя структуры. После имени следует целое число, указывающее количество членов структуры. За подсчётом членов следуют удвоенное число объектов. Каждый член — пара, содержащая символ имени члена и объект, являющийся значением этого члена.
Если имя структуры не соответствует подклассу Struct в работающей версии ruby, должно быть выброшено исключение.
Если существует несоответствие между структурой в текущей версии ruby и количеством членов в сериализованной структуре, должно быть выброшено исключение.
Пользовательский Class
“C” обозначает подкласс String, Regexp, Array или Hash. После байта типа следует символ, содержащий имя подкласса. После имени — обернутый объект.
Определённый пользователем
“u” обозначает объект с пользовательским форматом сериализации, использующим метод экземпляра _dump и метод класса _load. После байта типа следует символ, содержащий имя класса. После имени класса следует последовательность байтов, содержащая пользовательское представление объекта.
Метод класса _load вызывается для класса со строкой, созданной из последовательности байтов.
Пользовательский Marshal
“U” обозначает объект с пользовательским форматом сериализации, использующим методы экземпляра marshal_dump и marshal_load. После байта типа следует символ, содержащий имя класса. После имени класса следует объект, содержащий данные.
При загрузке необходимо выделить новый экземпляр и вызвать метод marshal_load для экземпляра с данными.
Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.