If you implemented this in ConsumeInteger(), it would not follow the usual
symbol lookup semantics used everywhere else in the language.  For example,
you would not be able to refer to enums defined later in the file, or
defined in a different file.  You might be able to handle enums defined
inside a message, but it would be hacky.
Put another way, I would expect this to work:

  import "baz.proto";

  message Bar {
    enum Ids { BAR = 2; }

  message OuterMessage {
    optional int32 foo = FOO;
    optional int32 bar = Bar.BAR;
    optional int32 baz = BAZ;  // defined in baz.proto

  enum Ids { FOO = 1; }

While we could just say "Sorry, you can only use enums defined in the same
file, *above* the point where they are first used, and not nested in any
other message.", these restrictions are totally different from the lookup
semantics of any other symbol and would thus be confusing and hard to learn.
 And eventually someone will want to fix these problem anyway.

So, the way you'd have to implement this is to extend the
FieldDescriptorProto message to allow the field number to be specified as a
string, then resolve that string in the cross-linking phase of
DescriptorBuilder (in src/google/protobuf/descriptor.cc).  I think this is
kind of hairy.

I think a much better solution would be to generate some sort of symbolic
constants for field numbers that can be accessed at runtime, so that you
don't have to generate a separate enum.  This would only require updating
the code generators.  Then you don't need to define an enum in the .proto
file at all.

For a field called foo_bar, I think the corresponding field number constant
should be kFooBarFieldNumber in C++ and FOO_BAR_FIELD_NUMBER in Java.  Not
sure what the preferred style is in Python.

If you'd like to make this change, it should be a pretty easy modification
to google/protobuf/compiler/{cpp/cpp,java/java}_{message,extension}.cc,
google/protobuf/compiler/python/python_generator.cc, and appropriate unit

What do you think?

On Tue, Apr 7, 2009 at 5:44 AM, Michael Poole <mdpo...@troilus.org> wrote:

> One of the suggested techniques for union types looks (almost) like this:
>  message OneMessage {
>    required int32 type = 1;
>    extensions 100 to max;
>  }
>  enum ExtensionType { FOO = 100; BAR = 101; BAZ = 102; }
>  extend OneMessage {
>    optional Foo foo_ext = 100;
>    optional Bar bar_ext = 101;
>    optional Baz baz_ext = 102;
>  }
> C++ code that reads OneMessage messages would often like to switch on
> the "type" field; unfortunately, the constants that identify foo_ext,
> bar_ext and baz_ext are only given in the generated .pb.cc file, and
> cannot be evaluated for use in a C++ "case" statement.
> As the number of optional elements increases, the duplication of
> values in the enum and their associated extension identifiers grows,
> and managing the mapping between them becomes an egregious violation
> of the "Don't Repeat Yourself" principle.
> To help manage this, I am inclined to write a patch to allow
> google::protobuf::compiler::ConsumeInteger() to look up previously
> defined enum values and return their integer values, so that one could
> instead write:
>  extend OneMessage {
>    optional Foo foo_ext = FOO;
>    // et cetera..
>  }
> So, three questions:
> 1.) Is there a better way to solve the C++ switch/case problem?
> 2.) Is this a reasonable approach within the architecture of the
>    Protocol Buffers compiler?  (That is, if the patch is clean,
>    might it be rejected for design reasons?)
> 3.) Assuming the previous two answers indicate a patch is in order,
>    what is the best way to submit the patch?
> Michael Poole
> >

You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
For more options, visit this group at 

Reply via email to