• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • CPACK
    • Home
    • List packs
    • Submit pack
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
    • SWISH Prolog shell
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

1.4 The low-level SWI-Prolog Implementation
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • Google's Protocol Buffers Library
        • Google's Protocol Buffers
          • The low-level SWI-Prolog Implementation
            • Wiretypes
            • Tags (field numbers)
            • Basic Usage
            • Alternation, Aggregation, Encapsulation, and Enumeration
            • Groups (deprecated)
            • Advanced Topics

1.4.3 Basic Usage

A protobuf wire-stream is a byte string that is comprised of zero or more of the above multi-byte wire-stream primitives. Templates are lists of Prolog terms. Each term corresponds to a production rule in the DCG. The purpose of the template is to provide a recipe and value set for encoding and decoding a particular message. Each term in the template has an arity of two. The term's functor is the local "host type". Argument 1 is its tag (field number), which must always be ground, and argument 2 is its associated value, which may or may not be ground.

A protobuf "message" is a list of fields and is encoded in the template as protobufs([Field1, Field2, ...]), where each field is of the form Type(Tag,Value and Type can be any scalar or compound type.

Scalar fields are encoded as Type(Tag,Value). For example, if a field is defined in a .proto file by optional string some_field = 10, then it could be encoded by string(10,"some field's contents") or by atom(10, 'some field\'s contents').

Repeated fields are done by repeated(Tag,Type([Value1,Value2,...]), where Type is any type.

Embedded messages are done by embedded(Tag,protobuf([Field1,Field2,...])) (this is the same =protobuf(...)= as is used at the top level).

Repeated embedded messages are done by repeated_embedded(Tag,protobuf([Field1,Field2,...]),Fields), which gets repeated items and combines them into a list. For example, repeated_embedded(Tag, protobuf([string(1,_Key),string(2,_Value)]), Fields) could unify Fields to [protobuf([string(1,"key1"),string(2,"value1")]), protobuf([string(1,"key2"),string(2,"value2")])]. Note that the variables in the protobuf part of the term do not get instantiated: they are similar to the Template in findall/3 and similar.

Note: It is an error to attempt to encode a message using a template that is not ground. Decoding a message into a template that has unbound variables has the effect of unifying the variables with their corresponding values in the wire-stream.

Assume a .proto definition:

message Command {
  optional string msg_type = 1;
  optional string command  = 2;
  optional int32  x        = 3;
  optional int32  y        = 4;
}

Map a Prolog structure to a Protocol Buffer:

%! command(+Term, -Proto) is det.
% Map a Prolog term to a corresponding protobuf term.
command(add(X,Y), Proto) :-
   freeze(X, must_be(integer, X)),  % for debugging
   freeze(Y, must_be(integer, Y)),  % for debugging
   Proto = protobuf([atom(1, command),
                     atom(2, add),
                     integer(3, X),
                     integer(4, Y)
                    ]).

Later on:

   ... prepare X, Y for command/2 ...

   command(add(X,Y), Proto),
   protobuf_message(Proto, WireCodes),

   % send the message
   open('filename', write, Stream, [encoding(octet),type(binary)]),
   format(Stream, '~s', [WireCodes]),
   close(Stream)

Proto is the protobuf template. Each template describes exactly one message. WireCodes is the wire-stream, which encodes bytes (values between 0 and 255 inclusive). If you are interworking with other systems and languages, then the protobuf templates that you supply to protobuf_message/2 must be equivalent to those described in the .proto file that is used on the other side.

ClioPatria (version V3.1.1-51-ga0b30a5)