module Kwmarshal:sig..end
This module is a clone of Marshal that adds a tag and an
optional version number to the marshaled payload. These allow an
application to distinguish its own marshaled data from that of
another application, and generate useful error messages instead of
core dumps.
It also adds a file magic number (suitable for file(1)) to the
data, to be provide minimal information for non-OCaml programs.
Note that these functions actually use Marshal -- just in a
newly structured way -- so all the issues with Marshal apply
here (e.g. lack of type safety, issues with extensible variant
types, exceptions, and closures).
New versions of all the marshaling functions from Marshal are
provided with modified APIs:
to_ functions) take an additional
~tag parameter, and an optional ?version parameterfrom_ functions) also take, in
addition, an optional ?vequals parameter that can be used to
modify the default version number equality algorithm (Kwmarshal.vequals)~tag is a string that tags or labels the type of
marshaled data. It might be an application name, for example.
This tag is stored with the marshaled data to identify it.
When unmarshaling, you need to provide the same ~tag value; if
the given tag doesn't exactly match the tag stored with the
marshaled data, a Kwmarshal.WrongTag exception is raised.
If used, version numbers must "match" as well. The default is that the versions must match at the major version level.
The tag and version are stored in a Kwmarshal.header alongside your
payload. The unmarshaling functions return a pair of header *
'a, where 'a is the type of your marshaled payload. Here's an
example:
let s = to_string ~tag:"myapp" ("foo",12) [] in
(from_string ~tag:"myapp" s 0 : header * (string * int))type extern_flags =
| |
No_sharing |
(* |
Don't preserve sharing
| *) |
| |
Closures |
(* |
Send function closures
| *) |
| |
Compat_32 |
(* |
Ensure 32-bit compatibility
| *) |
val versionno : stringval magicprefix : stringtype header = {
|
tag : |
|
version : |
exception Bad
Kwmarshal magic number.exception WrongTag of string * string
The exception's parameter is the pair of expected tag, actual tag.
exception WrongVersion of string option * string option
The exception's parameter is the pair of expected version, actual version.
Versions numbers are string options. Not providing a ~version
parameter when unmarshaling (i.e., your given version is None)
means you don't want to check the version in the header.
A given ~version parameter of (Some g) never matches a header
version of None, and successfully matches a header version of
(Some h) iff vequals g h.
No syntax of the actual version "number" string is presumed except
by the default Kwmarshal.vequals function; if you override it, you can
use any syntax you like.
val fixflags : extern_flags list -> Marshal.extern_flags list
val vequals : string -> string -> boolvequals given header: is the given version number equal to the version number in the header?
This function assumes a version number syntax that matches the regexp ^[0-9]+[.]?;
the initial number is the major version number.
We compute equality as (m=n), where m is the given major
version number and n is the header's major version number.
given : the version number provided via the ?version parameterheader : the version number in the header of the marshaled dataval to_channel : tag:string ->
?version:string ->
Pervasives.out_channel -> 'a -> extern_flags list -> unitto_channel ~tag ?version chan payload flags: writes the representation of payload on channel chan.
The marshaled data includes a magic number and a Kwmarshal.header, so
only Kwmarshal.from_channel can unmarshal the data (Marshal.from_channel cannot).
tag : the tag that identifies this payloadversion : the optional version number of the payloadchan : the output channelpayload : the payloadflags : see Marshal.to_channelval from_channel : ?vequals:'a ->
tag:string ->
?version:string -> Pervasives.in_channel -> header * 'bfrom_channel ?vequals ~tag ?version chan: reads from channel
chan the byte representation of a structured value, as produced by one
of the Kwmarshal.to_* functions, and reconstructs and returns the
corresponding value.
The ~tag and ?version are observed as described above.
vequals : the equality function for version numberstag : the tag that identifies this payloadversion : the optional version number of the payloadchan : the output channelval to_bytes : tag:string -> ?version:string -> 'a -> extern_flags list -> bytesto_bytes ~tag ?version payload flags: returns a byte sequence
containing the representation of payload.
The marshaled data includes a magic number and a Kwmarshal.header, so
only Kwmarshal.from_bytes can unmarshal the data (Marshal.from_bytes cannot).
tag : the tag that identifies this payloadversion : the optional version number of the payloadpayload : the payloadflags : see Marshal.to_bytesval from_bytes : ?vequals:'a -> tag:string -> ?version:string -> bytes -> int -> 'b * 'cfrom_bytes ?vequals ~tag ?version bytes ofs: unmarshals a
structured value like Kwarshal.from_channel does, except that the byte
representation is not read from a channel, but taken from the byte
sequence buff, starting at position ofs.
The byte sequence is not mutated.
The ~tag and ?version are observed as described above.
vequals : the equality function for version numberstag : the tag that identifies this payloadversion : the optional version number of the payloadbytes : the byte sequenceval to_string : tag:string -> ?version:string -> 'a -> extern_flags list -> stringto_string ~tag ?version payload flags: Same as Kwmarshal.to_bytes but
return the result as a string instead of a byte sequence.
The marshaled data includes a magic number and a Kwmarshal.header, so
only Kwmarshal.from_string can unmarshal the data (Marshal.from_string cannot).
tag : the tag that identifies this payloadversion : the optional version number of the payloadpayload : the payloadflags : see Marshal.to_stringval from_string : ?vequals:'a -> tag:string -> ?version:string -> string -> int -> 'b * 'cfrom_string ?vequals ~tag ?version str ofs: Same as
Kwmarshal.from_bytes but takes a string as argument instead of a byte sequence.
The byte sequence is not mutated.
The ~tag and ?version are observed as described above.
vequals : the equality function for version numberstag : the tag that identifies this payloadversion : the optional version number of the payloadstr : the stringval to_buffer : tag:string ->
?version:string ->
bytes -> int -> int -> 'a -> extern_flags list -> intto_buffer ~tag ?version buff ofs len payload flags: marshals the
value payload, storing its byte representation in the sequence buff,
starting at index ofs, and writing at most len bytes.
It returns the number of bytes actually written to the
sequence. If the byte representation of payload does not fit in
len characters, the exception Failure is raised.
The marshaled data includes a magic number and a Kwmarshal.header, so
only Kwmarshal.from_bytes can unmarshal the data (Marshal.from_bytes cannot).
Raises Failure if payload won't fit in buff
tag : the tag that identifies this payloadversion : the optional version number of the payloadbuff : the bufferofs : the offset into the bufferlen : the size of the available buffer space (after ofs)payload : the payloadflags : see Marshal.to_string