2.3 Example: Heterogeneous Collections
The following example shows how one can specify a Protocol Buffer message that can deal with variable-length, unstructured bags of numbers:
compound_protobuf(complex(Real, Img), group(12, [double(1, Real), double(2, Img)])). compound_protobuf(float(Val), float(13, Val)). compound_protobuf(double(Val), double(14, Val)). compound_protobuf((Num rdiv Den), group(15, [integer(1, Num), integer(2, Den)])). compound_protobuf(integer(Val), integer(16, Val)). protobuf_bag([], []). protobuf_bag([ Type | More], Msg) :- compound_protobuf(Type, X), Proto = protobuf([embedded(1, protobuf([X]))]), protobuf_message(Proto, Msg, Msg1), protobuf_bag(More, Msg1), !.
Use it as follows:
?- protobuf_bag([complex(2,3), complex(4,5), complex(6,7), 355 rdiv -113, integer(11)], X). X = [10, 20, 99, 9, 0, 0, 0, 0, 0|...]. ?- protobuf_bag(Y, $X). Y = [complex(2.0, 3.0), complex(4.0, 5.0), complex(6.0, 7.0), 355 rdiv -113, integer(11)].
A protobuf description that is compatible with the above wire stream follows:
message compound_protobuf { optional group Complex = 12 { required double real = 1; required double img = 2; }; optional group Fraction = 15 { required sint64 num = 1; required sint64 den = 2; }; optional float float = 13; optional double double = 14; optional sint32 integer = 16; } message protobuf_bag { repeated compound_protobuf bag = 1;
Verify using the protobuf compiler's decoder:
$ protoc --decode=protobuf_bag pb-vector.proto <tmp96.tmp bag { Complex { real: 2 img: 3 } } bag { Complex { real: 4 img: 5 } } bag { Complex { real: 6 img: 7 } } bag { Fraction { num: 355 den: -113 } } bag { integer: 11 }