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.