For instance, I have some enums in my proto schema:
enum E1 {
UNKNOWN = 0;
OPTION_1 = 1;
OPTION_2 = 2;
OPTION_3 = 3;
}
enum E2 {
UNKNOWN = 0;
ANOTHER_OPTION_1 = 1;
ANOTHER_OPTION_2 = 2;
ANOTHER_OPTION_3 = 3;
}
message M {
E1 my_enum_1 = 1;
E2 my_enum_2 = 2;
}
I can generate scala classes with strings instead of enums by providing scalaPB
TypeMapper
s:
TypeMapper(_.name)(E1.fromName(_).get)
TypeMapper(_.name)(E2.fromName(_).get)
But I don't want to copypaste same TypeMappers for any single Enum
Is there any way to make only one TypeMapper for all enums with scalaPB
?
CodePudding user response:
Yes, this can be done.
If you want to make ScalaPB use String for all enums within a package, you can add package-scoped options file to tell ScalaPB to set the scala-type for each enum to a String
using field transformations:
// options.proto:
syntax = "proto3";
import "scalapb/scalapb.proto";
option (scalapb.options) = {
scope: PACKAGE,
field_transformations : [
{
when : {
type: TYPE_ENUM
}
set : {[scalapb.field] {type : 'String'}}
}
}
The next step will be to define a typemapper for all enums. Borrowing from Ivan's answer, this could be defined as follows:
implicit def enumMapper[E <: GeneratedEnum](implicit ec: GeneratedEnumCompanion[E]) =
TypeMapper[E, String](_.name)(ec.fromName(_).get)
If the above code is added to a package object in the same package as the generated code, or imported using the import
option in ScalaPB, the typemapper will be found in implicit search.
CodePudding user response:
You can't completely avoid defining TypeMapper
for each enum
type you have. But you could create a helper method to create TypeMapper
instances.
For example
import scalapb.GeneratedEnum
import scalapb.GeneratedEnumCompanion
import scalapb.TypeMapper
def enumMapper[E <: GeneratedEnum: GeneratedEnumCompanion] = {
TypeMapper[E, String](_.name)(implicitly[GeneratedEnumCompanion[E]].fromName(_).get)
}
---UPDATE---
Following on @thesamet comment, if you add implicit
to the method above and have it available in your implicit context, it will work.
This can be tested with following code that compiles
implicit def enumMapper...
val Enum1Mapper = implicitly[TypeMapper[E1]]