scalascalapb

How to generate any protobuf Enum as String with only one TypeMapper?


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 TypeMappers:

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?


Solution

  • 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.