Skip to content

Commit

Permalink
Implementing CombineCodec
Browse files Browse the repository at this point in the history
  • Loading branch information
nob13 committed Mar 31, 2023
1 parent 68daa12 commit affd157
Showing 1 changed file with 45 additions and 26 deletions.
Expand Up @@ -2,44 +2,63 @@ package net.reactivecore.cjs.util

import io.circe.Decoder.Result
import io.circe.{Codec, HCursor, JsonObject}
import scala.deriving.Mirror
import scala.compiletime.{erasedValue, summonInline}
import io.circe.Codec.AsObject
import io.circe.Json
import cats.implicits._

trait CombineCodec[T] {
def codec: Codec.AsObject[T]
}

object CombineCodec {
/*
implicit val nilCodec: CombineCodec[HNil] = new CombineCodec[HNil] {
override def codec: Codec.AsObject[HNil] = new Codec.AsObject[HNil] {
override def apply(c: HCursor): Result[HNil] = Right(HNil)

override def encodeObject(a: HNil): JsonObject = JsonObject()
implicit inline def genericCodec[T <: Product](using m: Mirror.ProductOf[T]): CombineCodec[T] = {
val tupleVariant = genericTuple[m.MirroredElemTypes]
val tupleConverter = listToTuple[m.MirroredElemTypes]
val c = new Codec.AsObject[T] {
def encodeObject(a: T): JsonObject = {
JsonObject.fromIterable ({
for {
(v, codec) <- a.productIterator.zip(tupleVariant)
(key, jsonValue) <- codec.encodeObject(v).toIterable.iterator
} yield (key, jsonValue)
}.toSeq)
}

def apply(c: HCursor): Result[T] = {
val parts = tupleVariant.map { codec =>
codec.apply(c)
}
parts.sequence.map { decoded =>
m.fromTuple(
tupleConverter(decoded)
)
}
}
}
new CombineCodec[T] {
def codec: AsObject[T] = c
}
}

implicit def elemCodec[H, T <: HList](
implicit hc: Codec.AsObject[H],
tc: CombineCodec[T]
): CombineCodec[H :: T] =
new CombineCodec[H :: T] {
override def codec: Codec.AsObject[H :: T] = Codec.AsObject.from[H :: T](
Codecs.combineDecoderA[H :: T, H, T]((a, b) => a :: b)(hc, tc.codec),
Codecs.combineEncoderU[H :: T, H, T](c => Some(c.head, c.tail))(hc, tc.codec)
)
private inline def genericTuple[T <: Tuple]: List[Codec.AsObject[Any]] = {
inline erasedValue[T] match {
case _: EmptyTuple => Nil
case _: (t *: ts) =>
val first = summonInline[Codec.AsObject[t]].asInstanceOf[Codec.AsObject[Any]]
val last = genericTuple[ts]
first :: last
}
*/
}

/*
implicit def genericCodec[T, G](implicit g: Generic.Aux[T, G], c: CombineCodec[G]): CombineCodec[T] = {
new CombineCodec[T] {
override def codec: Codec.AsObject[T] = Codec.AsObject.from(
c.codec.map(g.from),
c.codec.contramapObject(g.to)
)
private inline def listToTuple[T <: Tuple]: List[Any] => T = {
inline erasedValue[T] match {
case _: EmptyTuple => _ => EmptyTuple.asInstanceOf[T]
case _: (t *: ts) =>
list =>
(list.head.asInstanceOf[t] *: listToTuple[ts](list.tail)).asInstanceOf[T]
}
}*/

implicit def genericCodec[T]: CombineCodec[T] = {
???
}
}

0 comments on commit affd157

Please sign in to comment.