Spec-Zone.ru › Ruby 3.4

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»

Общая длина целого числа составляет три байта. Следующие два байта — положительное целое число в порядке от младшего байта к старшему.

«xfe»

Общая длина целого числа составляет три байта. Следующие два байта — отрицательное целое число в порядке от младшего байта к старшему.

«x03»

Общая длина целого числа составляет четыре байта. Следующие три байта — положительное целое число в порядке от младшего байта к старшему.

«xfd»

Общая длина целого числа составляет четыре байта. Следующие три байта — отрицательное целое число в порядке от младшего байта к старшему.

«x04»

Общая длина целого числа составляет пять байтов. Следующие четыре байта — положительное целое число в порядке от младшего байта к старшему. Для совместимости с 32-разрядной Ruby таким образом следует представлять только Fixnum меньше 1073741824. Для размеров объектов потока можно использовать полную точность.

«xfc»

Общая длина целого числа составляет пять байтов. Следующие четыре байта — отрицательное целое число в порядке от младшего байта к старшему. Для совместимости с 32-разрядной Ruby таким образом следует представлять только Fixnum больше -10737341824. Для размеров объектов потока можно использовать полную точность.

В противном случае первый байт представляет собой знаковое восьмибитное значение с расширением знака и смещением. Если значение положительное, оно определяется вычитанием 5 из значения. Если значение отрицательное, оно определяется прибавлением 5 к значению.

Для многих значений существует несколько вариантов представления. CRuby всегда выводит наиболее короткое возможное представление.

Символы и последовательности байтов

«:» обозначает настоящий символ. Настоящий символ содержит данные, необходимые для определения символа на оставшуюся часть потока, поскольку последующие вхождения в потоке будут ссылаться на него (ссылка на символ). Ссылка представляет собой 32-битное значение с индексацией от нуля (поэтому первое вхождение :hello имеет индекс 0).

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

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

"\x04\x08:\x0ahello"

«;» обозначает ссылку на Symbol, указывающую на ранее определённый Symbol. За байтом типа следует long, содержащий индекс связанного (указанного) Symbol в таблице поиска.

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

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

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

Ссылки на Object

Отдельно от ссылок на символы, но аналогичным образом, поток содержит только одну копию каждого объекта (определяемого по object_id) для всех объектов, за исключением true, false, nil, Fixnum и Symbol (которые хранятся отдельно, как описано выше). Для таких объектов сохраняется 32-битное значение с индексацией от единицы, которое повторно используется при следующем обнаружении объекта. (Индекс первого объекта — 1.)

«@» обозначает ссылку на объект. За байтом типа следует long, задающий индекс объекта.

Например, следующий поток содержит Array с одним и тем же объектом "hello" дважды:

"\004\b[\a\"\nhello@\006"

Переменные экземпляра

«I» указывает, что за следующим объектом следуют переменные экземпляра. За байтом типа следует объект. За объектом следует длина, указывающая количество переменных экземпляра объекта. За длиной следует набор пар «имя — значение». Имена являются символами, а значения — объектами. Символы должны быть именами переменных экземпляра (:@name).

Для Object (тип «o», описанный ниже) используется тот же формат переменных экземпляра, что и описанный здесь.

Для String и Regexp (описанных ниже) для указания Encoding используется специальная переменная экземпляра :E.

Расширение

«e» указывает, что следующий объект расширен модулем. За байтом типа следует объект. За объектом следует символ, содержащий имя модуля, которым расширен объект.

Array

«[» обозначает Array. За байтом типа следует long, указывающий количество объектов в массиве. За длиной следует указанное количество объектов.

Bignum

«l» обозначает Bignum, состоящий из трёх частей:

знак

Один байт, содержащий «+» для положительного значения или «-» для отрицательного.

длина

Long, указывающий количество следующих байтов данных Bignum, делённое на два. Чтобы определить количество следующих байтов данных, умножьте длину на два.

данные

Байты данных Bignum, представляющие число.

Следующий код Ruby восстановит значение Bignum из массива байтов:

result = 0

bytes.each_with_index do |byte, exp|
 result += (byte * 2 ** (exp * 8))
end

Класс и модуль

«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 со значением по умолчанию это значение следует за всеми парами.

Модуль и старый модуль

Object

«o» обозначает объект, не имеющий какой-либо другой специальной формы (например, определённого пользователем или встроенного формата). За байтом типа следует символ, содержащий имя класса объекта. За именем класса следует long, указывающий количество имён и значений переменных экземпляра объекта. За размером следует удвоенное указанное количество пар объектов.

Ключи в парах должны быть символами, содержащими имена переменных экземпляра.

Регулярное выражение

«/» обозначает регулярное выражение. За байтом типа следует последовательность байтов, содержащая исходный текст регулярного выражения. За байтом типа следует байт со значениями параметров регулярного выражения (регистронезависимость и т. д.) в виде знакового 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. За байтом типа следует символ, содержащий имя структуры. За именем следует long, указывающий количество членов структуры. За количеством членов следует удвоенное количество объектов. Каждый член представляет собой пару, содержащую символ члена и объект со значением этого члена.

Если имя структуры не соответствует подклассу Struct в запущенной Ruby, должно быть вызвано исключение.

Если структура в текущей запущенной Ruby и количество членов в сериализованной структуре не совпадают, должно быть вызвано исключение.

Пользовательский класс

«C» обозначает подкласс String, Regexp, Array или Hash. За байтом типа следует символ, содержащий имя подкласса. За именем следует обёрнутый объект.

Определяемый пользователем формат

«u» обозначает объект с определённым пользователем форматом сериализации, использующим метод экземпляра _dump и метод класса _load. За байтом типа следует символ, содержащий имя класса. За именем класса следует последовательность байтов, содержащая представление объекта, определённое пользователем.

Метод класса _load вызывается для класса со строкой, созданной из последовательности байтов.

Пользовательский Marshal

«U» обозначает объект с определённым пользователем форматом сериализации, использующим методы экземпляра marshal_dump и marshal_load. За байтом типа следует символ, содержащий имя класса. За именем класса следует объект, содержащий данные.

При загрузке необходимо выделить новый экземпляр и вызвать marshal_load для этого экземпляра, передав ему данные.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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