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

mess.codec.generic.DerivedDecoder.scala Maven / Gradle / Ivy

The newest version!
package mess.codec.generic

import export._
import mess.{Decoder, TypeMismatchError}
import mess.ast.MsgPack
import shapeless._
import shapeless.labelled.{FieldType, field}

trait DerivedDecoder[A] extends Decoder[A]

@exports
object DerivedDecoder extends LowPriorityDerivedDecoder

private[mess] trait LowPriorityDerivedDecoder {

  implicit final val decodeHNil: DerivedDecoder[HNil] =
    new DerivedDecoder[HNil] {
      def apply(a: MsgPack): Decoder.Result[HNil] = Right(HNil)
    }

  implicit final def decodeLabelledHList[K <: Symbol, H, T <: HList](
      implicit
      witK: Witness.Aux[K],
      decodeH: Decoder[H],
      decodeT: DerivedDecoder[T]): DerivedDecoder[FieldType[K, H] :: T] =
    new DerivedDecoder[FieldType[K, H] :: T] {
      def apply(m: MsgPack): Decoder.Result[FieldType[K, H] :: T] = m match {
        case MsgPack.MMap(a) =>
          decodeT(m) match {
            case Right(t) =>
              val v = a.getOrElse(MsgPack.MString(witK.value.name), MsgPack.MNil)
              decodeH(v) match {
                case Right(h) => Right(field[K](h) :: t)
                case Left(e)  => Left(e)
              }
            case Left(e) => Left(e)
          }
        case _ => Left(TypeMismatchError("FieldType[K, H] :: T", m))
      }
    }

  implicit final val decodeCNil: DerivedDecoder[CNil] =
    new DerivedDecoder[CNil] {
      override def apply(m: MsgPack): Decoder.Result[CNil] =
        Left(TypeMismatchError("CNil", m))
    }

  implicit final def decodeLabelledCCons[K <: Symbol, L, R <: Coproduct](
      implicit
      witK: Witness.Aux[K],
      decodeL: Decoder[L],
      decodeR: DerivedDecoder[R]): DerivedDecoder[FieldType[K, L] :+: R] = {
    new DerivedDecoder[FieldType[K, L] :+: R] {
      override def apply(m: MsgPack): Decoder.Result[FieldType[K, L] :+: R] = m match {
        case MsgPack.MMap(a) =>
          val v = a.getOrElse(MsgPack.fromString(witK.value.name), MsgPack.MNil)
          decodeL.map(v => Inl(field[K](v))).apply(v) match {
            case r @ Right(_) => r
            case Left(_)      => decodeR.map(vv => Inr(vv)).apply(m)
          }
        case _ => Left(TypeMismatchError("FieldType[K, L] :+: R", m))
      }
    }
  }

  implicit final def decodeGen[A, R](implicit
                                     gen: LabelledGeneric.Aux[A, R],
                                     decodeR: Lazy[DerivedDecoder[R]]): DerivedDecoder[A] =
    new DerivedDecoder[A] {
      def apply(a: MsgPack): Decoder.Result[A] = decodeR.value(a) match {
        case Right(v) => Right(gen.from(v))
        case Left(e)  => Left(e)
      }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy