Skip to content

Commit

Permalink
Update HttpContentCodec.scala
Browse files Browse the repository at this point in the history
  • Loading branch information
varshith257 authored Aug 31, 2024
1 parent 16e2e2f commit 1eeff37
Showing 1 changed file with 64 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import zio.http.codec.internal.TextBinaryCodec
import zio.http.internal.HeaderOps
import zio.http.template._

final case class HttpContentCodec[A](
choices: ListMap[MediaType, BinaryCodecWithSchema[A]],
sealed trait HttpContentCodec[A](
) { self =>

def choices: ListMap[MediaType, BinaryCodecWithSchema[A]]

private var lookupCache: Map[MediaType, Option[BinaryCodecWithSchema[A]]] = Map.empty

/**
Expand Down Expand Up @@ -176,6 +177,67 @@ final case class HttpContentCodec[A](

object HttpContentCodec {

private val schemaCache = scala.collection.mutable.Map[Schema[_], HttpContentCodec[_]]()

def from[A](
codec: (MediaType, BinaryCodecWithSchema[A]),
codecs: (MediaType, BinaryCodecWithSchema[A])*,
): HttpContentCodec[A] =
Default(ListMap((codec +: codecs): _*))

def fromSchema[A](implicit schema: Schema[A]): HttpContentCodec[A] = {
schemaCache.computeIfAbsent(schema, _ => json.only[A] ++ protobuf.only[A] ++ text.only[A])
.asInstanceOf[HttpContentCodec[A]]
}

private final case class Default[A](
choices: ListMap[MediaType, BinaryCodecWithSchema[A]]
) extends HttpContentCodec[A]

final case class Filtered[A](codec: HttpContentCodec[A], mediaType: MediaType) extends HttpContentCodec[A] {
override def choices: ListMap[MediaType, BinaryCodecWithSchema[A]] =
ListMap(mediaType -> codec.lookup(mediaType).getOrElse(
throw new IllegalArgumentException(s"MediaType $mediaType is not supported by $codec")
))
}

object json {
def only[A](implicit schema: Schema[A]): HttpContentCodec[A] =
fromSingleCodec(
MediaType.application.`json`,
JsonCodec.schemaBasedBinaryCodec[A](JsonCodec.Config())(schema),
schema
)
}

object protobuf {
def only[A](implicit schema: Schema[A]): HttpContentCodec[A] =
fromSingleCodec(
MediaType.parseCustomMediaType("application/protobuf").get,
ProtobufCodec.protobufCodec[A],
schema
)
}

object text {
def only[A](implicit schema: Schema[A]): HttpContentCodec[A] =
fromMultipleCodecs(
List(
MediaType.text.`plain` -> TextBinaryCodec.fromSchema(schema),
MediaType.application.`octet-stream` -> TextBinaryCodec.fromSchema(schema)
),
schema
)
}

private def fromSingleCodec[A](mediaType: MediaType, codec: BinaryCodec[A], schema: Schema[A]) = {
Default(ListMap(mediaType -> BinaryCodecWithSchema(codec, schema)))
}

private def fromMultipleCodecs[A](codecs: List[(MediaType, BinaryCodec[A])], schema: Schema[A]) = {
Default(ListMap(codecs.map { case (mt, codec) => mt -> BinaryCodecWithSchema(codec, schema) }: _*))
}

private final case class DefaultCodecError(name: String, message: String)

private object DefaultCodecError {
Expand Down

0 comments on commit 1eeff37

Please sign in to comment.