48

Is it possible to obtain the string equivalent of protobuf enums in C++?

e.g.:

The following is the message description:

package MyPackage;

message MyMessage
{
    enum RequestType
    {
        Login = 0;
        Logout = 1;
    }

    optional RequestType requestType = 1;
}

In my code I wish to do something like this:

MyMessage::RequestType requestType = MyMessage::RequestType::Login;

// requestTypeString will be "Login"
std::string requestTypeString = ProtobufEnumToString(requestType);
rmldts
  • 366
  • 3
  • 10
Alexandru Irimiea
  • 2,513
  • 4
  • 26
  • 46

2 Answers2

44

The EnumDescriptor and EnumValueDescriptor classes can be used for this kind of manipulation, and the the generated .pb.h and .pb.cc names are easy enough to read, so you can look through them to get details on the functions they offer.

In this particular case, the following should work (untested):

std::string requestTypeString = MyMessage_RequestType_Name(requestType);
Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • 2
    Small nitpick: The protobuf doc recommends not to use the global functions with mangled names, but instead the class scoped functions, so instead of `MyMessage_RequestType_Name`, use `MyMessage::RequestType_Name`. – EinfachToll Nov 03 '22 at 12:27
22

See the answer of Josh Kelley, use the EnumDescriptor and EnumValueDescriptor.

The EnumDescriptor documentation says:

  • To get a EnumDescriptor

    To get the EnumDescriptor for a generated enum type, call TypeName_descriptor(). Use DescriptorPool to construct your own descriptors.

  • To get the string value, use FindValueByNumber(int number)

    const EnumValueDescriptor * EnumDescriptor::FindValueByNumber(int number) const

    Looks up a value by number.

    Returns NULL if no such value exists. If multiple values have this >number,the first one defined is returned.

Example, get the protobuf enum:

enum UserStatus {
  AWAY = 0;
  ONLINE = 1;
  OFFLINE = 2;
}

The code to read the string name from a value and the value from a string name:

const google::protobuf::EnumDescriptor *descriptor = UserStatus_descriptor();

std::string name = descriptor->FindValueByNumber(UserStatus::ONLINE)->name();
int number = descriptor->FindValueByName("ONLINE")->number();

std::cout << "Enum name: " << name << std::endl;
std::cout << "Enum number: " << number << std::endl;
rmldts
  • 366
  • 3
  • 10
  • 1
    Watch the `->name()` and `->number()` at the end of those examples. They can be easy to miss and hard to figure out how to get them corrected. – Jonathan Geisler Dec 29 '20 at 21:29