Spec-Zone.ru › OCaml

Модуль Marshal

module Marshal: sig .. end

Сериализация структур данных.

Этот модуль предоставляет функции для кодирования произвольных структур данных в последовательности байтов, которые затем можно записать в файл или отправить через канал или сетевое соединение. Позже эти байты можно прочитать, возможно, в другом процессе, и декодировать обратно в структуру данных. Формат последовательностей байтов совместим на всех машинах для данной версии OCaml.

Предупреждение: в настоящее время сериализация не является типобезопасной. Тип сериализованных данных не передаётся вместе со значением, поэтому невозможно проверить, что прочитанные данные имеют тип, ожидаемый контекстом. В частности, результирующий тип функций Marshal.from_* указан как 'a, но это вводит в заблуждение: возвращаемое значение OCaml не имеет типа 'a для всех 'a; оно имеет один уникальный тип, который невозможно определить во время компиляции. Программисту следует явно указать ожидаемый тип возвращаемого значения, используя следующий синтаксис:

  • (Marshal.from_channel chan : type). Если объект в файле не принадлежит указанному типу, во время выполнения может произойти что угодно.

Значения расширяемых типов вариантов, например исключения (расширяемого типа exn), возвращаемые десериализатором, не следует сопоставлять с образцом с помощью match ... with или try ... with, поскольку десериализация не сохраняет информацию, необходимую для сопоставления их конструкторов. Структурное сравнение с другими значениями расширяемых типов вариантов также не работает. Большинство других способов использования, например Printexc.to_string, продолжат работать ожидаемым образом.

Представление сериализованных значений не предназначено для чтения человеком и содержит байты, не являющиеся печатными символами. Поэтому каналы ввода и вывода, используемые вместе с Marshal.to_channel и Marshal.from_channel, необходимо открывать в двоичном режиме, например с помощью open_out_bin или open_in_bin; каналы, открытые в текстовом режиме, приведут к ошибкам десериализации на платформах, где текстовые каналы отличаются от двоичных, например в Windows.

type extern_flags = 
| No_sharing (*

Не сохранять совместное использование

*)
| Closures (*

Передавать замыкания функций

*)
| Compat_32 (*

Обеспечить совместимость с 32-разрядными платформами

*)

Флаги для приведённых ниже функций Marshal.to_*.

val to_channel : out_channel -> 'a -> extern_flags list -> unit

Marshal.to_channel chan v flags записывает представление v в канал chan. Аргумент flags — это, возможно, пустой список флагов, определяющих поведение сериализации в отношении совместного использования, функциональных значений и совместимости между 32- и 64-разрядными платформами.

Если flags не содержит Marshal.No_sharing, циклические ссылки и совместное использование внутри значения v обнаруживаются и сохраняются в созданной последовательности байтов. В частности, это гарантирует, что сериализация всегда завершается. Однако совместное использование между значениями, сериализованными последовательными вызовами Marshal.to_channel, не обнаруживается и не сохраняется. Если flags содержит Marshal.No_sharing, совместное использование игнорируется. Это ускоряет сериализацию, если v не содержит совместно используемых подструктур, но может замедлить сериализацию и увеличить размер представления в байтах, если v действительно содержит совместное использование, а также привести к незавершению работы, если v содержит циклы.

Если flags не содержит Marshal.Closures, сериализация завершается ошибкой при обнаружении функционального значения внутри v: между разными программами можно безопасно передавать только «чистые» структуры данных, не содержащие ни функций, ни объектов. Если flags содержит Marshal.Closures, функциональные значения сериализуются как позиция в коде программы вместе со значениями, соответствующими свободным переменным, захваченным замыканием. В этом случае результат сериализации можно прочитать только в процессах, выполняющих в точности ту же программу с тем же скомпилированным кодом. (Это проверяется во время десериализации с помощью MD5-хеша кода, передаваемого вместе с позицией в коде.)

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

Если flags содержит Marshal.Compat_32, сериализация завершается ошибкой при обнаружении целочисленного значения вне диапазона -230, 230-1 целых чисел, представимых на 32-разрядной платформе. Это гарантирует, что данные, сериализованные на 64-разрядной платформе, можно безопасно прочитать на 32-разрядной платформе. Если flags не содержит Marshal.Compat_32, целочисленные значения вне диапазона -230, 230-1 сериализуются и могут быть прочитаны на 64-разрядной платформе, но при чтении на 32-разрядной платформе вызовут ошибку во время десериализации. Флаг Mashal.Compat_32 имеет значение только при сериализации на 64-разрядной платформе; при сериализации на 32-разрядной платформе он не действует.

  • Вызывает исключение Failure, если chan не находится в двоичном режиме.
val to_bytes : 'a -> extern_flags list -> bytes

Marshal.to_bytes v flags возвращает последовательность байтов, содержащую представление v. Аргумент flags имеет то же значение, что и у Marshal.to_channel.

  • Начиная с версии 4.02
val to_string : 'a -> extern_flags list -> string

То же, что и to_bytes, но результат возвращается в виде строки, а не последовательности байтов.

val to_buffer : bytes -> int -> int -> 'a -> extern_flags list -> int

Marshal.to_buffer buff ofs len v flags сериализует значение v, сохраняя его байтовое представление в последовательности buff, начиная с индекса ofs и записывая не более len байтов. Возвращает фактическое число байтов, записанных в последовательность. Если байтовое представление v не помещается в len символов, вызывается исключение Failure.

val from_channel : in_channel -> 'a

Marshal.from_channel chan считывает из канала chan байтовое представление структурированного значения, созданное одной из функций Marshal.to_*, восстанавливает и возвращает соответствующее значение.

  • Вызывает исключение
    • End_of_file, если chan уже находится в конце файла.
    • Failure, если конец файла достигнут во время самой десериализации или если chan не находится в двоичном режиме.
val from_bytes : bytes -> int -> 'a

Marshal.from_bytes buff ofs десериализует структурированное значение, как это делает Marshal.from_channel, за исключением того, что байтовое представление считывается не из канала, а берётся из последовательности байтов buff, начиная с позиции ofs. Последовательность байтов не изменяется.

  • Начиная с версии 4.02
val from_string : string -> int -> 'a

То же, что и from_bytes, но принимает строку вместо последовательности байтов.

val header_size : int

Байты, представляющие сериализованное значение, состоят из заголовка фиксированного размера и части данных переменного размера, размер которой можно определить по заголовку. Marshal.header_size — это размер заголовка в байтах. Marshal.data_size buff ofs — это размер части данных в байтах, если в buff начиная с позиции ofs хранится корректный заголовок. Наконец, Marshal.total_size buff ofs — это общий размер сериализованного значения в байтах. И Marshal.data_size, и Marshal.total_size вызывают исключение Failure, если buff, ofs не содержит корректного заголовка.

Чтобы считать байтовое представление сериализованного значения в последовательность байтов, программе сначала нужно прочитать в последовательность Marshal.header_size байтов, затем определить длину оставшейся части представления с помощью Marshal.data_size, убедиться, что последовательность достаточно велика для оставшихся данных, считать их и, наконец, вызвать Marshal.from_bytes для десериализации значения.

val data_size : bytes -> int -> int

См. Marshal.header_size.

val total_size : bytes -> int -> int

См. Marshal.header_size.

Marshal и безопасность доменов

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

© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/api/Marshal.html

Spec-Zone.ru

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