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 : string
val magicprefix : string
type
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 -> bool
vequals 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 -> unit
to_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_channel
val from_channel : ?vequals:'a ->
tag:string ->
?version:string -> Pervasives.in_channel -> header * 'b
from_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 -> bytes
to_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_bytes
val from_bytes : ?vequals:'a -> tag:string -> ?version:string -> bytes -> int -> 'b * 'c
from_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 -> string
to_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_string
val from_string : ?vequals:'a -> tag:string -> ?version:string -> string -> int -> 'b * 'c
from_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 -> int
to_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