Skip to main content

Proto3 CheatSheet

Why Protocol Buffers?

  • Protocol buffers are Google's language-independent, platform-independent, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler.
  • You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.
  • Protocol Buffers are Schema Of Messages. They are language agnostic.
  • They can be converted to binary and converted back to message formats using the code generated by the protoc compiler for various languages.

Syntax

  • each field in the message has a unique tag number
  • tags in the range 1 to 15 takes one byte to encode. 16 to 2047 takes two bytes. So 1 to 15 should be reserved for very frequently occurring message elements.
  • Never Change/Use The TagNumber Of A Message Field Which Was Removed
  • We should use reserved in case of message definition update.
  • Reserved fields are used in case if we need to add/remove new fields into message.
syntax = "proto3";
// Specify the syntax version
syntax = "proto3";

/**
Syntax For Declaring Message:
    message ${MessageName} {
        ${Scalar Value Type} ${FieldName1} = ${Tag Number1};
        ...
        ${Scalar Value Type} ${FieldNameN} = ${Tag NumberN};
    }
Default Values Will be applied any case if the message doesn't contain a existing field defined
in the message definition
*/

// Example Message
message MessageTypes {
    /*
    * Scalar Value Types
    */
    string stringType = 1; // A string must always contain UTF-8 encoded or 7-bit ASCII text. Default value = ""

    // Number Types, Default Value = 0
    int32 int32Type = 2; // Uses Variable Length Encoding. Inefficient For Negative Numbers, Instead Use sint32.
    int64 int64Type = 3; // Uses Variable Length Encoding. Inefficient For Negative Numbers, Instead Use sint64.
    uint32 uInt32Type = 4; // Uses Variable Length Encoding
    uint64 uInt64Type = 5; // Uses Variable Length Encoding
    sint32 sInt32Type = 6; // Uses Variable Length Encoding. They are efficient in encoding for negative numbers.
                           // Use this instead of int32 for negative numbers
    sint64 sInt64Type = 7; // Uses Variable Length Encoding. They are efficient in encoding for negative numbers.
    // Use this instead of int64 for negative numbers.

    fixed32 fixed32Type = 8; // Always four bytes. More efficient than uint32 if values are often greater than 2^28.
    fixed64 fixed64Type = 9; // Always eight bytes. More efficient than uint64 if values are often greater than 2^56

    sfixed32 sfixed32Type = 10; // Always four bytes.
    sfixed64 sfixed64Type = 11; // Always Eight bytes.

    bool boolType = 12; // Boolean Type. Default Value = false

    bytes bytesType = 13; // May contain any arbitrary sequence of bytes. Default Value = Empty Bytes

    double doubleType = 14;
    float floatType = 15;

    enum Week {
        UNDEFINED = 0; // Tag 0 is always used as default in case of enum
        SUNDAY = 1;
        MONDAY = 2;
        TUESDAY = 3;
        WEDNESDAY = 4;
        THURSDAY = 5;
        FRIDAY = 6;
        SATURDAY = 7;
    }
    Week wkDayType = 16;

    /*
    * Defining Collection Of Scalar Value Type
    * Syntax: repeated ${ScalarType} ${name} = TagValue
    */
    repeated string listOfString = 17; // List[String]
}



/*
* Defining Defined Message Types In Other Message Definition
*/
message Person {
    string fname = 1;
    string sname = 2;
}

message City {
    Person p = 1;
}




/*
* Nested Message Definitions
*/
message NestedMessages {
    message FirstLevelNestedMessage {
        string firstString = 1;
        message SecondLevelNestedMessage {
            string secondString = 2;
        }
    }
    FirstLevelNestedMessage msg = 1;
    FirstLevelNestedMessage.SecondLevelNestedMessage msg2 = 2;
}


/*
* Importing Message From A File
*/

// one.proto
message One {
    string oneMsg = 1;
}

// two.proto
import "myproject/one.proto"
message Two {
    string twoMsg = 2;
}



/**
 * Using reserverd fields
 */
message ReservedMessage {
    reserved 0, 1, 2, 3 to 10; // Set Of Tag Numbers Which Can't be reused.
    reserved "firstMsg", "secondMsg", "thirdMsg"; // Set Of Labels Which Can't Be reused.
}





/**
 * OneOf
 */
message OneOfMessage {
    oneof msg {
        string fname = 1;
        string sname = 2;
    };
}


/*
 * Maps
 */
message MessageWithMaps {
    map<string, string> mapOfMessages = 1;
}



/*
 * Services
 * Message Types Defined For Using In RPC system.
 * When protoc compiler generates for various languages it generates stub methods for the services.
 */

message SearchRequest {
    string queryString = 1;
}

message SearchResponse {
    string queryResponse = 1;
}
service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse);
}