Модуль 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.
Маршализация и безопасность областей
При работе с изменяемым значением, которое может быть изменено другим доменом, необходимо соблюдать осторожность. Изменение значения, которое передаётся в сериализованный вид (т.е. преобразуется в последовательность байтов), является ошибкой программирования и может привести к неожиданным значениям (при десериализации) из-за разрыва, поскольку сериализация подразумевает копирование по байту.
© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/api/Marshal.html