Oneof kind vs Enum in protobuf
Asked Answered
K

1

13

What's the difference between using an Enum and a oneof kind in protobuf3? As far as I can tell, an Enum restricts the field to be one of a predefined set of values, but so does the oneof kind.

Klenk answered 14/9, 2021 at 22:10 Comment(0)
D
5

Enums are named numbers. You define the names in the enum definition and assign them a value. An enum should always have the value zero it it's set.

enum State {
  A = 0;
  B = 1;
  C = 2;
}

Next you can use this enum in any of your message

message Update {
  State currentState = 1;
  State previousState = 2;
}

A oneof is something very different. It allows you to send different types but only allocate limited memory for them. This as you can only set one of those types at a time. This is similar to an union in C/C++ or a std::variant as of C++17.

Take this example in which we have a message, a integer and double defined in our oneof.

// The message in our oneof
message someMsg {
  // Multiple fields
}

// The message holding our oneof
message msgWithOneof {

  oneof theOneof {
    someMsg msg     = 1;
    int32   counter = 2;
    double  value   = 3;
  }
  // Feel free to add more fields her of before the oneof
}

You are only able to set msg, counter or value at one time. If you set another this will clear the other field.

Assuming an C/C++ implementation the largest field will determine the amount of memory allocated. Say someMsg is the largest, setting a integer or double will not be a problem as they fit in the same space. If you not use a oneof the total memory allocated would be the sum of sizeof(someMsg) + sizeof(int32) + sizeof(double).

There is some overhead to keep track which field has been set. In the google C++ implementation this is a bit in the presence variable. This is similar to fields which are marked optional.

Dissociate answered 15/9, 2021 at 6:58 Comment(2)
Minor addition to "different types", it also allows you to represent the same type, but with different semantic meaning - for example, msgWithOneof.theOneof could also have an additional double valueDelta = 4; and someMsg criticialMessage = 5; (but at most one of the values in theOneof can have a value at any one time)Binder
@MarcGravell Excellent remark. It is indeed very well possible to repeat the same type multiple times in a oneof yet allocate memory only once.Dissociate

© 2022 - 2025 — McMap. All rights reserved.