private def fromAvroInternal()

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


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

    // =======================================================================
    // 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"$tree.asInstanceOf[Boolean]"
        case t if t =:= typeOf[Int] =>
          q"$tree.asInstanceOf[Long].toInt"
        case t if t =:= typeOf[Long] =>
          q"$tree.asInstanceOf[Long]"
        case t if t =:= typeOf[Float] =>
          q"$tree.asInstanceOf[Double].toFloat"
        case t if t =:= typeOf[Double] =>
          q"$tree.asInstanceOf[Double]"
        case t if t =:= typeOf[String] =>
          q"$tree.toString"
        case t if t =:= typeOf[BigDecimal] =>
          q"_root_.com.spotify.scio.bigquery.Numeric.parse($tree)"
        case t if t =:= typeOf[ByteString] =>
          val b = q"$tree.asInstanceOf[_root_.java.nio.ByteBuffer]"
          q"_root_.com.google.protobuf.ByteString.copyFrom($b.asReadOnlyBuffer())"
        case t if t =:= typeOf[Array[Byte]] =>
          val b = q"$tree.asInstanceOf[_root_.java.nio.ByteBuffer]"
          q"_root_.java.util.Arrays.copyOfRange($b.array(), $b.position(), $b.limit())"
        case t if t =:= typeOf[Instant] =>
          q"_root_.com.spotify.scio.bigquery.Timestamp.parse($tree)"
        case t if t =:= typeOf[LocalDate] =>
          q"_root_.com.spotify.scio.bigquery.Date.parse($tree)"
        case t if t =:= typeOf[LocalTime] =>
          q"_root_.com.spotify.scio.bigquery.Time.parse($tree)"
        case t if t =:= typeOf[LocalDateTime] =>
          q"_root_.com.spotify.scio.bigquery.DateTime.parse($tree.toString)"
        case t if t =:= typeOf[Geography] =>
          q"_root_.com.spotify.scio.bigquery.types.Geography($tree.toString)"
        case t if t =:= typeOf[Json] =>
          q"_root_.com.spotify.scio.bigquery.types.Json($tree.toString)"
        case t if t =:= typeOf[BigNumeric] =>
          q"_root_.com.spotify.scio.bigquery.types.BigNumeric.parse($tree)"
        case t if isCaseClass(c)(t) =>
          val nestedRecord = TermName("r" + t.typeSymbol.name)
          q"""{
                val $nestedRecord = $tree.asInstanceOf[_root_.org.apache.avro.generic.GenericRecord]
                ${constructor(t, Ident(nestedRecord))}
              }
          """
        case _ => c.abort(c.enclosingPosition, s"Unsupported type: $tpe")
      }
    }

    def option(tree: Tree, tpe: Type): Tree =
      q"if ($tree == null) None else Some(${cast(tree, tpe)})"

    def list(tree: Tree, tpe: Type): Tree = {
      val jl = tq"_root_.java.util.List[AnyRef]"
      q"asScala($tree.asInstanceOf[$jl]).iterator.map(x => ${cast(q"x", tpe)}).toList"
    }

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

      val tree = q"$record.get($name)"
      if (tpe.erasure =:= typeOf[Option[_]].erasure) {
        option(tree, tpe.typeArgs.head)
      } else if (tpe.erasure =:= typeOf[List[_]].erasure) {
        list(tree, tpe.typeArgs.head)
      } else {
        cast(tree, tpe)
      }
    }

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

    // =======================================================================
    // Entry point
    // =======================================================================
    q"""(r: _root_.org.apache.avro.generic.GenericRecord) => {
          import _root_.scala.jdk.javaapi.CollectionConverters._
          ${constructor(tpe, q"r")}
        }
    """
  }