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).
За байтом типа следует последовательность байтов, которая состоит из long, указывающего на количество байтов в последовательности, за которым следует столько байтов данных. Последовательности байтов не имеют кодировки.
Например, следующий поток содержит Symbol :hello:
"\x04\x08:\x0ahello"
«;» представляет ссылку на Symbol, которая ссылается на ранее определённый Symbol. За байтом типа следует long, содержащий индекс в таблице поиска для связанного (ссылочного) Symbol.
Например, следующий поток содержит [:hello, :hello]:
"\x04\b[\a:\nhello;\x00"
Когда ниже упоминается «символ», может подразумеваться либо реальный символ, либо ссылка на символ.
Ссылки на Object
Отдельно от, но аналогично ссылкам на символы, поток содержит только один экземпляр каждого объекта (как определяется object_id) для всех объектов, кроме true, false, nil, Fixnums и Symbols (которые хранятся отдельно, как описано выше). При повторной встрече объекта будет сохранено и использовано одноиндексное 32-битное значение. (У первого объекта индекс 1).
«@» представляет ссылку на объект. За байтом типа следует long, указывающий индекс объекта.
Например, следующий поток содержит Array того же "hello" объекта дважды:
"\004\b[\a\"\nhello@\006"
Переменные экземпляра
«I» указывает, что за следующим объектом следуют переменные экземпляра. За байтом типа следует объект. За объектом следует длина, указывающая количество переменных экземпляра для объекта. За длиной следует набор пар имя-значение. Имена — это символы, а значения — это объекты. Символы должны быть именами переменных экземпляра (:@name).
Объект Object («тип o», описанный ниже) использует тот же формат для своих переменных экземпляра, что описан здесь.
Для String и Regexp (описанные ниже) используется специальная переменная экземпляра :E для указания Encoding.
Расширенный
«e» указывает, что следующий объект расширен модулем. За байтом типа следует объект. За объектом следует символ, содержащий имя модуля, которым расширен объект.
Array
“[” представляет Array. За байтом типа следует long, указывающий количество объектов в массиве. Указанное количество объектов следует за длиной.
Bignum
«l» представляет Bignum, состоящий из трёх частей:
- sign
-
Один байт, содержащий «+» для положительного значения или «-» для отрицательного значения.
- length
-
Long, указывающий количество байтов данных Bignum, которые следуют, делённых на два. Умножьте длину на два, чтобы определить количество байтов данных, которые следуют за ней.
- data
-
Байты данных 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). За байтом типа следует long, указывающий количество пар ключ-значение в Hash, размер. Указанное количество объектов следует за размером.
Для Hash с заданным значением по умолчанию значение по умолчанию следует за всеми парами.
Module и старый Module
Object
«o» обозначает объект, не имеющий никакого другого специального формата (например, пользовательского или встроенного). После байта типа следует символ, содержащий имя класса объекта. После имени класса следует целое число, указывающее количество имен и значений переменных экземпляра для объекта. После размера следуют удвоенное количество пар объектов.
Ключами в парах должны быть символы, содержащие имена переменных экземпляра.
Регулярное выражение
«/» представляет собой регулярное выражение. После байта типа следует последовательность байтов, содержащая исходный код регулярного выражения. После байта типа следует байт, содержащий опции регулярного выражения (нечувствительность к регистру и т. д.) в виде знакового 8-битного значения.
Регулярные выражения могут иметь кодировку, присоединенную через переменные экземпляра (см. выше). Если кодировка не присоединенна, необходимо удалить escape-последовательности для следующих спецсимволов 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–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.