Marshal Формат
Формат Marshal используется для сериализации объектов Ruby. Формат может хранить произвольные объекты с помощью трёх механизмов пользовательских расширений.
Для получения документации по использованию Marshal для сериализации и десериализации объектов, см. модуль Marshal.
В этом документе сериализованный набор объектов называется потоком. Реализация Ruby может загружать набор объектов из String, IO или объекта, реализующего метод getc.
Формат потока
Первые два байта потока содержат старшую и младшую версии, каждая как единичный байт, кодирующий цифру. Реализация Ruby использует версию 4.8 (хранится как «x04x08») и поддерживается ruby 1.8.0 и новее.
Разные главные версии формата Marshal несовместимы и не могут быть поняты другими главными версиями. Меньшие версии формата могут быть поняты более новыми версиями. Версию 4.7 может загрузить реализация 4.8, но реализация 4.7 не может загрузить версию 4.8.
За байтами версии следует поток, описывающий сериализованный объект. Поток содержит вложенные объекты (так же, как и объект 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, 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, который состоит из трёх частей:
- sign
-
Единый байт, содержащий «+» для положительного значения или «-» для отрицательного.
- length
-
Целое число, указывающее количество байтов данных 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). После байта типа следует целое число, указывающее количество пар ключ-значение в 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–2022 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.