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

medeia.generic.CoproductDecoderInstances.scala Maven / Gradle / Ivy

The newest version!
package medeia.generic

import cats.data.NonEmptyChain
import cats.syntax.eq._
import cats.syntax.either._
import medeia.decoder.BsonDecoderError.InvalidTypeTag
import medeia.decoder.StackFrame.Case
import medeia.decoder.{BsonDecoder, BsonDecoderError}
import medeia.syntax._
import shapeless.labelled.{FieldType, field}
import shapeless.{:+:, CNil, Coproduct, Inl, Inr, Witness}

trait CoproductDecoderInstances {
  implicit def cnilDecoder[Base](implicit
      options: SealedTraitDerivationOptions[Base] = SealedTraitDerivationOptions[Base]()
  ): ShapelessDecoder[Base, CNil] = { bsonDocument =>
    val typeTag = bsonDocument.getSafe(options.discriminatorKey).flatMap(_.fromBson[String])
    typeTag match {
      case Left(value)  => Left(value)
      case Right(value) => Left(NonEmptyChain(InvalidTypeTag(value)))
    }
  }

  implicit def coproductDecoder[Base, K <: Symbol, H, T <: Coproduct](implicit
      witness: Witness.Aux[K],
      hInstance: BsonDecoder[H],
      tInstance: ShapelessDecoder[Base, T],
      options: SealedTraitDerivationOptions[Base] = SealedTraitDerivationOptions[Base]()
  ): ShapelessDecoder[Base, FieldType[K, H] :+: T] = { bsonDocument =>
    val instanceDiscriminator = options.transformDiscriminator(witness.value.name)

    def doDecode(discriminatorFromBson: String): Either[NonEmptyChain[BsonDecoderError], FieldType[K, H] :+: T] = {
      if (discriminatorFromBson === instanceDiscriminator) {
        hInstance.decode(bsonDocument).map((x: H) => Inl(field[K](x))).leftMap(_.map(_.push(Case(instanceDiscriminator))))
      } else {
        tInstance.decode(bsonDocument).map(Inr(_))
      }
    }

    for {
      discriminatorField <- bsonDocument.getSafe(options.discriminatorKey)
      discriminatorFromBson <- discriminatorField.fromBson[String]
      result <- doDecode(discriminatorFromBson)
    } yield result
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy