Spec-Zone.ru › Ruby 3.1

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 бита с индексом 0 (поэтому первое появление :hello — 0).

После байта типа следует последовательность байтов, которая состоит из целого числа, указывающего количество байтов в последовательности, за которым следует столько байтов данных. Последовательности байтов не имеют кодировки.

Например, следующий поток содержит Symbol :hello:

"\x04\x08:\x0ahello"

«;” представляет собой ссылку на Symbol, которая ссылается на ранее определенный Symbol. После байта типа следует целое число, содержащее индекс в таблице поиска для связанного (ссылочного) Symbol.

Например, следующий поток содержит [:hello, :hello]:

"\x04\b[\a:\nhello;\x00"

Когда ниже упоминается «символ», может быть настоящий символ или ссылка на символ.

Ссылки на Object

Отдельно от, но аналогично ссылкам на символы, поток содержит только один экземпляр каждого объекта (как определяется object_id) для всех объектов, кроме true, false, nil, Fixnums и Symbols (которые хранятся отдельно, как описано выше). Будет храниться целое значение 32 бита с индексом 1 и повторно использоваться, когда объект будет встречен снова. (Первый объект имеет индекс 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API