Did you know ... Search Documentation:
Pack msgpackc -- prolog/msgpackc.pl
PublicShow source

The predicates have three general categories.

  1. High-order recursive for normal use by application software.
  2. Parameterised mid-level grammar components such as msgpack_nil designed for two-way unification between fundamental types and their MessagePack byte encoded representations.
  3. 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.

- 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.
  1. The nil object becomes Prolog nil atom rather than [] which Prolog calls "nil," the empty list termination. Prolog [] decodes an empty MessagePack array.
  2. Booleans become Prolog atoms false and true.
  3. Integers become Prolog integers.
  4. 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.
  5. Strings in UTF-8 become Prolog strings, never atoms.
  6. Arrays become Prolog lists.
  7. 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)