1.6.3 Encapsulation and Enumeration
It is possible to embed one protocol buffer specification inside
another using the embedded
term. The following example
shows a vector of numbers being placed in an envelope that contains a
command enumeration.
Enumerations are a compact method of sending tokens from one system
to another. Most occupy only two bytes in the wire-stream. An
enumeration requires that you specify a callable predicate like commands/2,
below. The first argument is an atom specifying the name of token, and
the second is an non-negative integer that specifies the token's value.
These must of course, match a corresponding enumeration in the
.proto
file.
Note: You must expose this predicate to the protobufs module by assigning it explicitly.
protobufs:commands(Key, Value) :- commands(Key, Value). commands(square, 1). commands(decimate, 2). commands(transform, 3). commands(inverse_transform, 4). basic_vector(Type, Proto) :- vector_type(Type, Tag), Proto = protobuf([ repeated(Tag, Type) ]). send_command(Command, Vector, Msg) :- basic_vector(Vector, Proto1), Proto = protobuf([enum(1, commands(Command)), embedded(2, Proto1)]), protobuf_message(Proto, Msg).
Use it as follows:
?- send_command(square, double([1,22,3,4]), Msg). Msg = [8, 1, 18, 36, 17, 0, 0, 0, 0, 0, 0, 240, 63, 17, 0, 0, 0, 0, 0, 0, 54, 64, 17, 0, 0, 0, 0, 0, 0, 8, 64, 17, 0, 0, 0, 0, 0, 0, 16, 64]. ?- send_command(Cmd, V, $Msg). Cmd = square, V = double([1.0, 22.0, 3.0, 4.0]) .
Compatibility Note: The protobuf grammar (protobuf-2.1.0) permits enumerations to assume negative values. This requires them to be encoded as integers. But Google's own Golden Message unit-test framework has enumerations encoded as unsigned. Consequently, parsers that encode them as integers cannot properly parse the Golden Message. So it's probably a good idea to avoid negative values in enumerations. Our parser forbids it anyway.