Spec-Zone.ru › Ruby 2.6

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).

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

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

"\x04\x08:\x0ahello"

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

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

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

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

Ссылки на Object

Отдельно от, но аналогично ссылкам на символы, поток содержит только одну копию каждого объекта (определяемого с помощью object_id) для всех объектов, кроме true, false, nil, Fixnum и 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, который состоит из трех частей:

знак

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

длина

Long, указывающий количество байтов данных 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. (Объекты данных — обернутые указатели из расширений 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-битного значения.

Регулярные выражения могут иметь кодировку, присоединенную через переменные экземпляра (см. выше). Если кодировка не указана, символы экранирования для следующих специальных символов 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–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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