private def fromTableRowInternal()

in scio-google-cloud-platform/src/main/scala/com/spotify/scio/bigquery/types/ConverterProvider.scala [266:334]


  private def fromTableRowInternal(c: blackbox.Context)(tpe: c.Type): c.Tree = {
    import c.universe._

    val ops = q"_root_.com.spotify.scio.bigquery.syntax.TableRowOps"
    val bs = q"_root_.com.google.protobuf.ByteString"

    // =======================================================================
    // Converter helpers
    // =======================================================================
    def cast(tree: Tree, tpe: Type): Tree = {
      val provider: OverrideTypeProvider = OverrideTypeProviderFinder.getProvider
      tpe match {
        case t if provider.shouldOverrideType(c)(t) => provider.createInstance(c)(t, q"$tree")
        case t if t =:= typeOf[Boolean]             => q"$ops.boolean($tree)"
        case t if t =:= typeOf[Int]                 => q"$ops.int($tree)"
        case t if t =:= typeOf[Long]                => q"$ops.long($tree)"
        case t if t =:= typeOf[Float]               => q"$ops.float($tree)"
        case t if t =:= typeOf[Double]              => q"$ops.double($tree)"
        case t if t =:= typeOf[String]              => q"$ops.string($tree)"
        case t if t =:= typeOf[BigDecimal]          => q"$ops.numeric($tree)"
        case t if t =:= typeOf[Array[Byte]]         => q"$ops.bytes($tree)"
        case t if t =:= typeOf[ByteString]          => q"$bs.copyFrom($ops.bytes($tree))"
        case t if t =:= typeOf[Instant]             => q"$ops.timestamp($tree)"
        case t if t =:= typeOf[LocalDate]           => q"$ops.date($tree)"
        case t if t =:= typeOf[LocalTime]           => q"$ops.time($tree)"
        case t if t =:= typeOf[LocalDateTime]       => q"$ops.datetime($tree)"
        case t if t =:= typeOf[Geography]           => q"$ops.geography($tree)"
        case t if t =:= typeOf[Json]                => q"$ops.json($tree)"
        case t if t =:= typeOf[BigNumeric]          => q"$ops.bignumeric($tree)"
        case t if isCaseClass(c)(t)                 =>
          // nested records
          val r = TermName("r" + t.typeSymbol.name)
          q"""{
            val $r = $ops.record($tree)
            ${constructor(t, r)}
          }"""
        case _ => c.abort(c.enclosingPosition, s"Unsupported type: $tpe")
      }
    }

    def field(symbol: Symbol, row: TermName): Tree = {
      val name = symbol.name.toString
      val tpe = symbol.asMethod.returnType

      tpe match {
        case t if t.erasure =:= typeOf[Option[_]].erasure =>
          q"$ops.nullable($name)($row).map(x => ${cast(q"x", t.typeArgs.head)})"
        case t if t.erasure =:= typeOf[List[_]].erasure =>
          q"$ops.repeated($name)($row).map(x => ${cast(q"x", t.typeArgs.head)})"
        case t =>
          q"${cast(q"$ops.required($name)($row)", t)}"
      }
    }

    def constructor(tpe: Type, row: TermName): Tree = {
      val companion = tpe.typeSymbol.companion
      val gets = tpe.erasure match {
        case t if isCaseClass(c)(t) => getFields(c)(t).map(s => field(s, row))
        case _                      => c.abort(c.enclosingPosition, s"Unsupported type: $tpe")
      }
      q"$companion(..$gets)"
    }

    // =======================================================================
    // Entry point
    // =======================================================================
    val r = TermName("r")
    q"($r: ${typeOf[TableRow]}) => ${constructor(tpe, r)}"
  }