The predicates have three general categories.
- High-order recursive for normal use by application software.
- Parameterised mid-level grammar components such as
msgpack_nil
designed for two-way unification between fundamental types and
their MessagePack byte encoded representations.
- Low-level C predicates and functions interfacing with the machine
byte-swapping hardware.
Optimal message packing
Prolog has the uncanny ability to find optimal solutions to seemingly
intractible problems. Back-tracking allows the message sender to search
for the shortest message possible amongst all available encodings. In
most cases, message transmittion latency presents the narrowest
bottleneck. Encoding and decoding is just one small part. As message
frequency and complexity increases, an optimal encoding might improve
overall messaging throughput over channels with limited bandwidth.
Optimisation could complete in microseconds whereas transmission
improvements might aggregate to milliseconds.
- author
- - Roy Ratcliffe
- msgpack(?Term:compound)// is nondet
- Where Term is a compound arity-1 functor, never a list term. The
functor carries the format choice.
Packing arrays and maps necessarily recurses. Array elements are
themselves objects; arrays are objects hence arrays of arrays
nested up to any number of dimensions. Same goes for maps.
- msgpack_object(?Object)// is semidet
- Encodes and decodes a single MessagePack object. Term encodes an
object as follows.
- The nil object becomes Prolog
nil
atom rather than []
which Prolog calls "nil," the empty list termination. Prolog []
decodes an empty MessagePack array.
- Booleans become Prolog atoms
false
and true
.
- Integers become Prolog integers.
- Floats become Prolog floats. Distinguishing between 32- and
64-bit float-point occurs by wrapping the Prolog-side in
float(Precision, Number)
terms where Precision selects 32 or 64
bits. Setting up an epsilon threshold allows for automatic
precision adjustment when encoding.
- Strings in UTF-8 become Prolog strings, never atoms.
- Arrays become Prolog lists.
- Maps become Prolog dictionaries.
Unsigned and signed integers share a common pattern. The
least-significant two bits, 00 through 11, select eight through 64
bits of width. The ordering of the MessagePack specification
arranges the types in order to exploit this feature.
Prolog has no native type for raw binary objects in the vein of R's
raw vector.
Notice that integer comes before float. This is important because
Prolog integers can render as floats and vice versa provided that
the integer is signed; it fails if unsigned.
- msgpack_objects(?Objects)// is semidet
- Zero or more MessagePack objects.
- msgpack_nil// is semidet
- msgpack_false// is semidet
- msgpack_true// is semidet
- The simplest packing formats for nil and Booleans.
- msgpack_float(?Float)// is semidet
- msgpack_float(?Width, ?Float)// is nondet
- Delivers two alternative solutions by design, both valid. Uses the
different renderings to select the best compromise between 32- and
64-bit representation for any given number. Prolog lets the
implementation explore the alternatives. Chooses 32 bits only when
the least-significant 32 bits match zero. In this case, the 64-bit
double representation is redundant because the 32-bit representation
fully meets the resolution requirements of the float value.
The arity-1 (+) mode version of the predicate duplicates the
encoding assumptions. The structure aims to implement precision
width selection but without re-rendering. It first unifies a
64-bit float with eight bytes. Parsing from bytes to Float will fail
if the bytes run out at the end of the byte stream.
Predicates float32//1 and float64//1 unify with integer-valued
floats as well as floating-point values. This provides an
alternative representation for many integers.
- msgpack_int(?Int:integer)// is semidet
- Finds the optimum integer representation, shortest first. Tries
fixed integer at first which works for a small subset of integers
between -32 and 127. If that fails because the integer falls outside
that small range, the second attempt applies unsigned
representation; it only applies signed formats for negatives. This
assumes that the difference does not matter. An overlap exists
between signed and unsigned integers.
- msgpack_fixint(?Width, ?Int)// is semidet
- Width is the integer bit width, only 8 and never 16, 32 or 64.
- msgpack_uint(?Width, ?Int)// is nondet
- msgpack_int(?Width, ?Int)// is nondet
- msgpack_str(?Str)// is semidet
- Unifies Str with the shortest packed UTF-8 string message.
- msgpack_fixstr(?Str)// is semidet
- Unifies MessagePack byte codes with fixed Str of length between
0 and 31 inclusive.
- msgpack_str(?Width, ?Str)// is semidet
- Refactors common string-byte unification utilised by all string
grammars for the MessagePack protocol's 8, 16 and 32 bit lengths.
Unifies for Length number of bytes for Str. Length is not the
length of Str in Unicodes but the number of bytes in its UTF-8
representation.
- msgpack_bin(?Bytes)// is semidet
- Succeeds only once when Bytes unifies with the MessagePack byte
stream for the first time. Relies on the width ordering: low to
high and attempts 8 bits first, 16 bits next and finally 32. Fails
if 32 bits is not enough to unify the number of bytes because the
byte-list has more than four thousand megabytes.
- msgpack_bin(?Width, ?Bytes:list)// is nondet
- Works very much like the string grammar except that the Bytes remain
as 8-bit byte lists.
- msgpack_array(:OnElement, ?Array:list)// is semidet
- Unify with Array using OnElement as the per-element grammar
predicate.
- msgpack_map(:OnPair, ?Map:list)// is semidet
- Unify with Map using OnPair as the pair-wise grammar.
- msgpack_ext(?Term)// is semidet
- In (++) mode, meaning fully ground with no variables, the ++Term
first unifies Term with its Type and Ext bytes using
type_ext_hook/3 multi-file predicate.
- msgpack_ext(?Type, ?Ext)// is semidet
- Type is a signed integer. Ext is a list of byte codes.
Undocumented predicates
The following predicates are exported, but not or incorrectly documented.
- msgpack_false(Arg1, Arg2)
- msgpack_true(Arg1, Arg2)
- msgpack_float(Arg1, Arg2, Arg3, Arg4)
- msgpack_int(Arg1, Arg2, Arg3, Arg4)