Sealed oneofs
Sealed oneofs are a subset of oneofs for which ScalaPB generates idiomatic data types for.
#
ExampleNote 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.
#
Sealed oneof rulesA 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_value
must 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.
#
Optional sealed oneofThis is a variant of Sealed oneof, where the optionality is expressed differently.
The 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: