Search code examples
protocol-buffersscalapb

ScalaPB TypeMapper for custom primitive wrappers not found


I am using

addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.23")
libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.9.0-M7"

I have some custom primitive wrappers (we are not using google wrappers)

syntax = "proto3";

package com.github.piotrkowalczuk.ntypes;

// Int32 represents a int32 that may be nil.
message Int32 {
    int32 int32 = 1;
    bool valid = 2;
}

and then I would like to use the primitive wrapper message Int32 in another message but with automatically unnesting the wrapped value in Scala case class:

syntax = "proto3";

package com.github.fpopic;

import "scalapb/scalapb.proto";
import "ntypes.proto";

message Usage {
    com.github.piotrkowalczuk.ntypes.Int32 ntype_primitive = 1 [(scalapb.field).type = "Option[Int]"];
}

and I created a simple Main.scala to specify custom TypeMapper

package com.github.fpopic

import com.github.piotrkowalczuk.ntypes.ntypes.Int32
import scalapb.TypeMapper

object Main {

  implicit val ntypeInt32ToInt: TypeMapper[Int32, Option[Int]] =
    TypeMapper[Int32, Option[Int]] {
      ntypeInt32: Int32 => if (ntypeInt32.valid) Some(ntypeInt32.int32) else None
    } {
      optInt: Option[Int] => Int32(optInt.getOrElse(0), valid = optInt.isDefined)
    }

  def main(args: Array[String]): Unit = {

    implicitly[TypeMapper[Int32, Option[Int]]]

    val u: Usage = new Usage(
      ntypePrimitive = Option(1234)
    )

  }
}

So would like to get in Scala Option[Int] instead of Option[Int32] or even Option[Option[Int]] that gets double-wrapped because every message gets Option automatically.

but I am getting error:

No TypeMapper found for conversion between com.github.piotrkowalczuk.ntypes.ntypes.Int32 and Option[Int].

Solution

  • This can be achieved by setting no_box on this field to true, in addition to custom type of Option[Int].

    To make it possible for the generated code to find the implicit typemapper, you can put it in a package object for the same package as the generated code (or any of its parents)

    package com.github
    
    package object fpopic {
      implicit val myTypemapper = ...
    }