Sealed oneofs are a subset of oneofs for which ScalaPB generates idiomatic data types for.
Note that the name of the oneof name is
sealed_value. This is what makes ScalaPB treat
Expr as a sealed oneof and generate code similar to the following:
The above Scala representation of the protocol buffer is much nicer to work with than the default oneof representation, as there are no wrapper types around each individual case of the oneof. Also note that optional fields of type
Expr are not boxed inside an
Option since we have
Expr.Empty that represents the empty case.
A sealed oneof is detected when a message (denoted below as the containing message) contains a oneof named
sealed_value. The code generator checks the following rules for each sealed oneof. If any of these rules fail, then the code generator aborts.
The oneof named
sealed_valuemust be the only oneof in the containing message.
No additional fields (except those inside
sealed_values) may be defined inside the containing message.
No nested messages or enums are allowed to be defined in the containing message.
All of the oneof cases must be inside the same namespace as the containing message. That is, all messages must either be top-level or direct children of the same parent message.
All the oneof cases must defined in the same file as the sealed oneof.
A message type can appear in at most one sealed oneof.
Sealed oneofs and the fields within them can not be typemapped to custom types.
Some of the rules above are inherently required (for example, that the message types need to be distinct). Other rules, such as the one requesting that all involved messages need to be inside the same namespace, were added to make the implementation simpler. That particular rule helps ensuring that all the cases can be generated into a single Scala source file without changing too much the existing way the code generator works. It is possible that some of the rules will change over time, though most likely they are only going to become less restrictive so existing code does not break.
Currently, sealed oneofs are implemented as a custom type defined over the old-style container message. This implementation detail is exposed through
asMessage which returns the underlying message representing the sealed oneof. It is possible that in a future version, sealed oneofs would have a direct implementation, and therefore
asMessage and its return type should be considered an experimental API.
This is a variant of Sealed oneof, where the optionality is expressed differently.
Empty case is not generated, but instead the sealed trait is put in other classes as
Option[_], not directly.
To create an optional sealed oneof, name the oneof sealed_value_optional as in the example below: