All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sksamuel.avro4s.decoders.eithers.scala Maven / Gradle / Ivy

package com.sksamuel.avro4s.decoders

import com.sksamuel.avro4s.{Avro4sDecodingException, Decoder, TypeGuardedDecoding}
import com.sksamuel.avro4s.avroutils.SchemaHelper
import org.apache.avro.Schema

trait EitherDecoders:
  given eitherDecoder[A, B](using leftDecoder: Decoder[A],
                            leftGuard: TypeGuardedDecoding[A],
                            rightDecoder: Decoder[B],
                            rightGuard: TypeGuardedDecoding[B]): Decoder[Either[A, B]] = new Decoder[Either[A, B]] {

    override def decode(schema: Schema): Any => Either[A, B] = {
      require(schema.isUnion)

      val leftSchema = SchemaHelper.extractEitherLeftSchema(schema)
      val rightSchema = SchemaHelper.extractEitherRightSchema(schema)

      val leftDecode = leftDecoder.decode(leftSchema)
      val rightDecode = rightDecoder.decode(rightSchema)

      val leftP: PartialFunction[Any, Boolean] = leftGuard.guard(leftSchema)
      val rightP: PartialFunction[Any, Boolean] = rightGuard.guard(rightSchema)

      // how do we know whether the incoming value should be decoded to a a left or a right ?
      // we can compare types for primitives, and if a record we can compare schemas
      { value =>
        if (leftP.isDefinedAt(value)) {
          Left(leftDecode(value))
        } else if (rightP.isDefinedAt(value)) {
          Right(rightDecode(value))
        } else {
          val nameA = leftSchema.getFullName
          val nameB = rightSchema.getFullName
          throw new Avro4sDecodingException(s"Could not decode $value into Either[$nameA, $nameB]", value)
        }
      }
    }
  }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy