Google Protocol Buffer: Custom Options with Repeated Fields

We encountered a question about Google protocol buffer: could we create a custom option which has a repeated decoration?

The protocol buffer compiler, protoc, answers: no.

However, it is OK to create an option with a message type, and the message could contain a repeated field. Here follows an example program.

The content of learn.proto:

import "google/protobuf/descriptor.proto";

message Something {
  repeated int32 a = 1;
}

extend google.protobuf.FieldOptions {
  optional float my_field_option = 50002;
  optional Something my_another_field_option = 50003;
}

message MyMessage {
  optional string my_field = 1
    [(my_field_option) = 1.1];
  optional string my_another_field = 2
    [(my_another_field_option) = { a : [111, 222, 333] } ];
}

The content of learn.cc:

#include <iostream>
#include <google/protobuf/descriptor.h>
#include "learn.pb.h"

int main() {
  MyMessage m;
  const ::google::protobuf::Descriptor* msg_desc = m.descriptor();
  {
    const ::google::protobuf::FieldDescriptor* field_desc =
      msg_desc->FindFieldByName("my_field");
    const ::google::protobuf::FieldOptions& field_options =
      field_desc->options();
    float option = field_options.GetExtension(my_field_option);
    std::cout << "my_field_option = \n" << option << "\n";
  }
  {
    const ::google::protobuf::FieldDescriptor* field_desc =
      msg_desc->FindFieldByName("my_another_field");
    const ::google::protobuf::FieldOptions& field_options =
      field_desc->options();
    Something option =
      field_options.GetExtension(my_another_field_option);
    std::cout << "my_another_field_option = \n"
              << option.DebugString() << "\n";
  }

  return 0;
}

The content of Makefile:

learn : learn.pb.h learn.pb.cc learn.cc
	g++ -o learn learn.cc learn.pb.cc -lprotobuf && ./learn

learn.pb.h : learn.proto
	protoc learn.proto --cpp_out=. \
          --proto_path=/Users/wyi/Downloads/protobuf-2.4.1/src/:.

The execution result is as so:

my_field_option =
1.1
my_another_field_option =
a: 111
a: 222
a: 333

Few more words here. The field option in protocol buffer has been inherited by the Go programming language and becomes struct tag. As described in the Go language specification:

A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. The tags are made visible through a reflection interface but are otherwise ignored.

As you see, struct tags in Go are restricted to be strings — no repeated decoration, no message type.