Spec-Zone.ru › Ruby 3

модуль Marshal

Библиотека маршалинга преобразует коллекции Ruby-объектов в поток байтов, позволяя сохранять их вне текущего активного скрипта. Эти данные впоследствии можно прочитать и восстановить исходные объекты.

В маршализованных данных хранятся главные и второстепенные номера версии вместе с информацией об объекте. При обычном использовании маршалинг может загружать только данные, записанные с тем же главным номером версии и равным или меньшим второстепенным номером версии. Если флаг «verbose» Ruby установлен (обычно с помощью -d, -v, -w или –verbose), то главные и второстепенные номера должны точно совпадать. Marshal версия независима от версий Ruby. Вы можете извлечь версию, прочитав первые два байта маршализованных данных.

str = Marshal.dump("thing")
RUBY_VERSION   #=> "1.9.0"
str[0].ord     #=> 4
str[1].ord     #=> 8

Некоторые объекты не могут быть сохранени: если сохраняемые объекты включают привязки, процедурные или метод-объекты, экземпляры класса IO или одиночные объекты, будет возбуждено исключение TypeError.

Если ваш класс имеет особые требования к сериализации (например, если вы хотите сериализовать в определенном формате) или содержит объекты, которые иначе не могут быть сериализованы, вы можете реализовать собственную стратегию сериализации.

Есть два способа сделать это: ваш объект может определить либо marshal_dump и marshal_load, либо _dump и _load. marshal_dump будет иметь приоритет над _dump, если оба определены. marshal_dump может привести к более коротким Marshal строкам.

Безопасность

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

В результате, Marshal.load не подходит в качестве универсального формата сериализации, и вы никогда не должны демаршализовать входные данные пользователя или другие недоверенные данные.

Если вам нужно десериализовать недоверенные данные, используйте JSON или другой формат сериализации, который может загружать только простые «примитивные» типы, такие как String, Array, Hash и т. д. Никогда не допускайте, чтобы входные данные пользователя указывали произвольные типы для десериализации.

marshal_dump и marshal_load

При сохранении объекта вызывается метод marshal_dump. marshal_dump должен вернуть результат, содержащий информацию, необходимую для marshal_load для восстановления объекта. Результатом может быть любой объект.

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

Пример:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def marshal_dump
    [@name, @version]
  end

  def marshal_load array
    @name, @version = array
  end
end

_dump и _load

Используйте _dump и _load, когда вам нужно самостоятельно выделить объект, который вы восстанавливаете.

При сохранении объекта вызывается метод экземпляра _dump с целым числом Integer, которое указывает максимальную глубину объектов для сохранения (значение -1 означает, что вы должны отключить проверку глубины). _dump должен вернуть строку String, содержащую информацию, необходимую для восстановления объекта.

Метод класса _load должен принять строку String и использовать ее для возвращения объекта того же класса.

Пример:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def _dump level
    [@name, @version].join ':'
  end

  def self._load args
    new(*args.split(':'))
  end
end

Так как Marshal.dump выводит строку, вы можете задать _dump возвращать строку Marshal, которая загружается Marshal в _load для сложных объектов.

Константы

MAJOR_VERSION

главная версия

MINOR_VERSION

второстепенная версия

Открытые методы класса

dump( obj [, anIO] , limit=-1 ) → anIO Показать исходный код
static VALUE
marshal_dump(int argc, VALUE *argv, VALUE _)
{
    VALUE obj, port, a1, a2;
    int limit = -1;

    port = Qnil;
    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
    if (argc == 3) {
        if (!NIL_P(a2)) limit = NUM2INT(a2);
        if (NIL_P(a1)) io_needed();
        port = a1;
    }
    else if (argc == 2) {
        if (FIXNUM_P(a1)) limit = FIX2INT(a1);
        else if (NIL_P(a1)) io_needed();
        else port = a1;
    }
    return rb_marshal_dump_limited(obj, port, limit);
}

Сериализует obj и все дочерние объекты. Если anIO указан, сериализованные данные будут записаны в него, в противном случае данные будут возвращены как строка String. Если limit указан, обход дочерних объектов будет ограничен этой глубиной. Если limit отрицательный, проверка глубины не будет производиться.

class Klass
  def initialize(str)
    @str = str
  end
  def say_hello
    @str
  end
end

(не производит вывода)

o = Klass.new("hello\n")
data = Marshal.dump(o)
obj = Marshal.load(data)
obj.say_hello  #=> "hello\n"

Marshal не может сохранять следующие объекты:

  • анонимный класс/модуль.

  • объекты, связанные с системой (например: Dir, File::Stat, IO, File, Socket и т. д.)

  • экземпляр MatchData, Data, Method, UnboundMethod, Proc, Thread, ThreadGroup, Continuation

  • объекты, которые определяют одиночные методы

load( source [, proc] ) → obj Показать исходный код
restore( source [, proc] ) → obj
static VALUE
marshal_load(int argc, VALUE *argv, VALUE _)
{
    VALUE port, proc;

    rb_check_arity(argc, 1, 2);
    port = argv[0];
    proc = argc > 1 ? argv[1] : Qnil;
    return rb_marshal_load_with_proc(port, proc);
}

Возвращает результат преобразования сериализованных данных в источнике в Ruby-объект (возможно, с ассоциированными подчиненными объектами). source может быть экземпляром IO или объектом, который отвечает на to_str. Если proc указан, каждый объект будет передан в proc по мере десериализации.

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

load( source [, proc] ) → obj Показать исходный код
restore( source [, proc] ) → obj
static VALUE
marshal_load(int argc, VALUE *argv, VALUE _)
{
    VALUE port, proc;

    rb_check_arity(argc, 1, 2);
    port = argv[0];
    proc = argc > 1 ? argv[1] : Qnil;
    return rb_marshal_load_with_proc(port, proc);
}

Возвращает результат преобразования сериализованных данных в источнике в Ruby-объект (возможно, с ассоциированными подчиненными объектами). source может быть экземпляром IO или объектом, который отвечает на to_str. Если proc указан, каждый объект будет передан в proc по мере десериализации.

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

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

Spec-Zone.ru

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