Формат сериализации
Формат Marshal используется для сериализации объектов Ruby. Формат может хранить произвольные объекты через три механизма пользовательских расширений.
Для получения документации по использованию Marshal для сериализации и десериализации объектов см. модуль Marshal.
В этом документе сериализованный набор объектов называется потоком. Реализация Ruby может загружать набор объектов из строки, объекта 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 и целое число большого размера
«i» представляет знаковое 32-битовое значение, используемое в упакованном формате. За типом следуют от одного до пяти байтов. Загружаемое значение всегда будет Fixnum. На 32-битных платформах (где точность Fixnum меньше 32 бит) загрузка больших значений вызовет переполнение в CRuby.
Тип fixnum используется для представления как объектов ruby Fixnum, так и размеров сериализованных массивов, хэшей, переменных экземпляра и других типов. В следующих разделах «целое число большого размера» будет означать формат, описанный ниже, который поддерживает полную 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_id) для всех объектов, кроме true, false, nil, Fixnums и Symbols (которые хранятся отдельно, как описано выше). При повторной встрече объекта будет храниться и повторно использоваться 32-битовое значение с индексом 1. (У первого объекта индекс 1).
«@» представляет ссылку на объект. За байтом типа следует целое число большого размера, задающее индекс объекта.
Например, следующий поток содержит массив объектов "hello" дважды:
"\004\b[\a\"\nhello@\006"
Переменные экземпляра
«I» указывает на то, что за следующим объектом следуют переменные экземпляра. За байтом типа следует объект. За объектом следует длина, указывающая количество переменных экземпляра для объекта. За длиной следует набор пар имя-значение. Имена являются символами, а значения — объектами. Символы должны быть именами переменных экземпляра (:@name).
Объект «o» (описанный ниже) использует тот же формат для своих переменных экземпляра, что и описанный здесь.
Для строк и регулярных выражений (описанных ниже) используется специальная переменная экземпляра :E, чтобы указать кодировку Encoding.
Расширенное
«e» указывает, что следующий объект расширен модулем. За байтом типа следует объект. За объектом следует символ, содержащий имя модуля, которым расширен объект.
Массив
«[» представляет собой массив. За байтом типа следует целое число большого размера, указывающее количество объектов в массиве. За длиной следуют указанное количество объектов.
Числа большой точности
«l» представляет собой число большой точности, которое состоит из трех частей:
- знак
-
Один байт, содержащий «+» для положительного значения или «-» для отрицательного.
- длина
-
Целое число большого размера, указывающее количество байтов данных числа большой точности, разделённых на два. Умножьте длину на два, чтобы определить количество байтов данных, которые следуют за ней.
- данные
-
Байты данных числа большой точности, представляющие число.
Следующий код Ruby восстановит значение числа большой точности из массива байтов:
result = 0 bytes.each_with_index do |byte, exp| result += (byte * 2 ** (exp * 8)) end
Класс и модуль
«c» представляет собой объект класса, «m» представляет собой объект модуля, а «M» представляет собой либо класс, либо модуль (это старый стиль для совместимости). Содержимое класса или модуля не включается, этот тип — только ссылка.
Переменные экземпляра не разрешены для классов или модулей.
Если класс или модуль не существует, должно быть поднято исключение.
Для типов «c» и «m» загружаемый объект должен быть классом или модулем соответственно.
«d» представляет собой объект Данные. (Объекты данных — это обернутые указатели из расширений Ruby.) После байта типа — символ, обозначающий класс для объекта Данные, и объект, который содержит состояние объекта Данные.
Для сохранения объекта Данные Ruby вызывает _dump_data. Для загрузки объекта Данные Ruby вызывает _load_data с состоянием объекта в новом экземпляре.
Число с плавающей точкой
«f» представляет собой объект число с плавающей точкой. После байта типа следует последовательность байтов, содержащая значение числа с плавающей точкой. Следующие значения являются специальными:
- “inf”
-
Положительная бесконечность
- “-inf”
-
Отрицательная бесконечность
- “nan”
-
Не число
В противном случае последовательность байтов содержит двойное значение C (загружаемое функцией strtod(3)). Более старые второстепенные версии Marshal также хранили дополнительные биты мантиссы для обеспечения переносимости между платформами, но версия 4.8 не включает их. См.
- ruby-talk:69518
-
для некоторых пояснений.
Хэш и хэш со значением по умолчанию
«{» представляет собой объект хэш, а «}» — хэш с заданным значением по умолчанию (Hash.new
0). После байта типа следует целое число большого размера, указывающее количество пар ключ-значение в хэше, размер. За размером следуют удвоенное количество объектов.
Для хэша со значением по умолчанию значение по умолчанию следует за всеми парами.
Модуль и старый модуль
Объект
«o» представляет собой объект, не имеющий другого специального формата (например, пользовательского или встроенного). После байта типа следует символ, содержащий имя класса объекта. После имени класса следует целое число большого размера, указывающее количество имён и значений переменных экземпляра для объекта. За размером следуют удвоенное количество пар объектов.
Ключи в парах должны быть символами, содержащими имена переменных экземпляра.
Регулярное выражение
«/» представляет собой регулярное выражение. После байта типа следует последовательность байтов, содержащая исходный код регулярного выражения. После байта типа следует байт, содержащий параметры регулярного выражения (регистронезависимое сравнение и т.д.) как знаковое 8-битовое значение.
Регулярные выражения могут иметь присоединённую кодировку через переменные экземпляра (см. выше). Если кодировка не прикреплена, escape-последовательности для следующих спецсимволов regexp, отсутствующих в ruby 1.8, должны быть удалены: g-m, o-q, u, y, E, F, H-L, N-V, X, Y.
Строка
'“' представляет строку. После байта типа следует последовательность байтов, содержащая содержимое строки. При выгрузке из ruby 1.9 переменная кодировки (:E см. выше) должна быть включена, если кодировка не двоичная.
Структура
“S” представляет структуру. После байта типа следует символ, содержащий имя структуры. После имени следует целое число, указывающее количество членов в структуре. После подсчёта членов следуют двойное количество объектов. Каждый член представляет собой пару, содержащую символ члена и объект, являющийся значением этого члена.
Если имя структуры не соответствует подклассу структуры в используемом ruby, должно быть вызвано исключение.
Если есть несоответствие между структурой в текущей версии ruby и количеством членов в сериализованной структуре, должно быть вызвано исключение.
Пользовательский Класс
“C” представляет подкласс String, Regexp, Array или Hash. После байта типа следует символ, содержащий имя подкласса. После имени следует обернутый объект.
Определенный пользователем
“u” представляет объект с пользовательским форматом сериализации, использующим метод _dump и метод класса _load. После байта типа следует символ, содержащий имя класса. После имени класса следует последовательность байтов, содержащая пользовательское представление объекта.
Метод класса _load вызывается для класса с строкой, созданной из последовательности байтов.
Пользовательский Маршалл
“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.