com.github.plokhotnyuk.jsoniter_scala.circe.CirceCodecs.scala Maven / Gradle / Ivy
The newest version!
package com.github.plokhotnyuk.jsoniter_scala.circe
import com.github.plokhotnyuk.jsoniter_scala.core._
import io.circe._
import java.time._
/**
* Implicit instances of circe's codec for `BigInt` and `java.time.*` types.
*
* Uses jsoniter-scala for efficient encoding and decoding.
*/
object CirceCodecs {
private[this] val pool = new ThreadLocal[(JsonReader, Array[Byte], JsonWriter)] {
override def initialValue(): (JsonReader, Array[Byte], JsonWriter) = {
val buf = new Array[Byte](512) // should be enough for the longest number or zoned date time value
new Tuple3(new JsonReader(buf, charBuf = new Array[Char](512)), buf, new JsonWriter(buf))
}
}
private[this] val readerConfig = ReaderConfig.withAppendHexDumpToParseException(false)
.withPreferredBufSize(512).withMaxBufSize(512).withPreferredCharBufSize(512).withMaxCharBufSize(512)
private[this] val writeConfig = WriterConfig.withPreferredBufSize(512)
private[this] class ShortAsciiStringCodec[A](codec: JsonValueCodec[A], name: String) extends Codec[A] {
override def apply(x: A): Json = {
val tlb = pool.get
val buf = tlb._2
io.circe.JsoniterScalaCodec.asciiStringToJString(buf, tlb._3.write(codec, x, buf, 0, 512, writeConfig))
}
override def apply(c: HCursor): Decoder.Result[A] = {
val tlb = pool.get
val buf = tlb._2
val s = io.circe.JsoniterScalaCodec.stringValue(c)
var len = 0
if ((s ne null) && {
len = s.length
len <= 510
} && {
buf(0) = '"'
var bits, i = 0
while (i < len) {
val ch = s.charAt(i)
buf(i + 1) = ch.toByte
bits |= ch
i += 1
}
buf(i + 1) = '"'
bits < 0x80
}) {
try return new scala.util.Right(tlb._1.read(codec, buf, 0, len + 2, readerConfig))
catch { case _: JsonReaderException => }
}
error(c)
}
private[this] def error(c: HCursor): Decoder.Result[A] = new scala.util.Left(DecodingFailure(name, c.history))
}
// codecs for numeric types
implicit val byteC3C: Codec[Byte] = io.circe.JsoniterScalaCodec.byteCodec {
val codec: JsonValueCodec[Byte] = new JsonValueCodec[Byte] {
@inline
override def decodeValue(in: JsonReader, default: Byte): Byte = {
val x = in.readByte(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Byte, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Byte = 0
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val shortC3C: Codec[Short] = io.circe.JsoniterScalaCodec.shortCodec {
val codec: JsonValueCodec[Short] = new JsonValueCodec[Short] {
@inline
override def decodeValue(in: JsonReader, default: Short): Short = {
val x = in.readShort(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Short, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Short = 0
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val intC3C: Codec[Int] = io.circe.JsoniterScalaCodec.intCodec {
val codec: JsonValueCodec[Int] = new JsonValueCodec[Int] {
@inline
override def decodeValue(in: JsonReader, default: Int): Int = {
val x = in.readInt(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Int, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Int = 0
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val longC3C: Codec[Long] = io.circe.JsoniterScalaCodec.longCodec {
val codec: JsonValueCodec[Long] = new JsonValueCodec[Long] {
@inline
override def decodeValue(in: JsonReader, default: Long): Long = {
val x = in.readLong(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Long, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Long = 0L
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val floatC3C: Codec[Float] = io.circe.JsoniterScalaCodec.floatCodec {
val codec: JsonValueCodec[Float] = new JsonValueCodec[Float] {
@inline
override def decodeValue(in: JsonReader, default: Float): Float = {
val x = in.readFloat(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Float, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Float = 0.0f
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val doubleC3C: Codec[Double] = io.circe.JsoniterScalaCodec.doubleCodec {
val codec: JsonValueCodec[Double] = new JsonValueCodec[Double] {
@inline
override def decodeValue(in: JsonReader, default: Double): Double = {
val x = in.readDouble(isToken = false)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: Double, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Double = 0.0
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val bigIntC3C: Codec[BigInt] = io.circe.JsoniterScalaCodec.bigIntCodec {
val codec: JsonValueCodec[BigInt] = new JsonValueCodec[BigInt] {
@inline
override def decodeValue(in: JsonReader, default: BigInt): BigInt = {
val x = in.readBigInt(isToken = false, default, JsonReader.bigIntDigitsLimit)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: BigInt, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: BigInt = null
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
implicit val bigDecimalC3C: Codec[BigDecimal] = io.circe.JsoniterScalaCodec.bigDecimalCodec {
val codec: JsonValueCodec[BigDecimal] = new JsonValueCodec[BigDecimal] {
@inline
override def decodeValue(in: JsonReader, default: BigDecimal): BigDecimal = {
val x = in.readBigDecimal(isToken = false, default, JsonReader.bigDecimalMathContext,
JsonReader.bigDecimalScaleLimit, JsonReader.bigDecimalDigitsLimit)
if (in.hasRemaining()) in.decodeError("expected '\"'")
x
}
@inline
override def encodeValue(x: BigDecimal, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: BigDecimal = null
}
s =>
pool.get._1.read(codec, s, readerConfig)
}
// codecs for java.time.* types
implicit val durationC3C: Codec[Duration] = new ShortAsciiStringCodec(new JsonValueCodec[Duration] {
@inline
override def decodeValue(in: JsonReader, default: Duration): Duration = in.readDuration(default)
@inline
override def encodeValue(x: Duration, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Duration = null
}, "Duration")
implicit val instantC3C: Codec[Instant] = new ShortAsciiStringCodec(new JsonValueCodec[Instant] {
@inline
override def decodeValue(in: JsonReader, default: Instant): Instant = in.readInstant(default)
@inline
override def encodeValue(x: Instant, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Instant = null
}, "Instant")
implicit val localDateC3C: Codec[LocalDate] = new ShortAsciiStringCodec(new JsonValueCodec[LocalDate] {
@inline
override def decodeValue(in: JsonReader, default: LocalDate): LocalDate = in.readLocalDate(default)
@inline
override def encodeValue(x: LocalDate, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: LocalDate = null
}, "LocalDate")
implicit val localDateTimeC3C: Codec[LocalDateTime] = new ShortAsciiStringCodec(new JsonValueCodec[LocalDateTime] {
@inline
override def decodeValue(in: JsonReader, default: LocalDateTime): LocalDateTime = in.readLocalDateTime(default)
@inline
override def encodeValue(x: LocalDateTime, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: LocalDateTime = null
}, "LocalDateTime")
implicit val localTimeC3C: Codec[LocalTime] = new ShortAsciiStringCodec(new JsonValueCodec[LocalTime] {
@inline
override def decodeValue(in: JsonReader, default: LocalTime): LocalTime = in.readLocalTime(default)
@inline
override def encodeValue(x: LocalTime, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: LocalTime = null
}, "LocalTime")
implicit val monthDayC3C: Codec[MonthDay] = new ShortAsciiStringCodec(new JsonValueCodec[MonthDay] {
@inline
override def decodeValue(in: JsonReader, default: MonthDay): MonthDay = in.readMonthDay(default)
@inline
override def encodeValue(x: MonthDay, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: MonthDay = null
}, "MonthDay")
implicit val offsetDateTimeC3C: Codec[OffsetDateTime] = new ShortAsciiStringCodec(new JsonValueCodec[OffsetDateTime] {
@inline
override def decodeValue(in: JsonReader, default: OffsetDateTime): OffsetDateTime = in.readOffsetDateTime(default)
@inline
override def encodeValue(x: OffsetDateTime, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: OffsetDateTime = null
}, "OffsetDateTime")
implicit val offsetTimeC3C: Codec[OffsetTime] = new ShortAsciiStringCodec(new JsonValueCodec[OffsetTime] {
@inline
override def decodeValue(in: JsonReader, default: OffsetTime): OffsetTime = in.readOffsetTime(default)
@inline
override def encodeValue(x: OffsetTime, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: OffsetTime = null
}, "OffsetTime")
implicit val periodC3C: Codec[Period] = new ShortAsciiStringCodec(new JsonValueCodec[Period] {
@inline
override def decodeValue(in: JsonReader, default: Period): Period = in.readPeriod(default)
@inline
override def encodeValue(x: Period, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Period = null
}, "Period")
implicit val yearMonthC3C: Codec[YearMonth] = new ShortAsciiStringCodec(new JsonValueCodec[YearMonth] {
@inline
override def decodeValue(in: JsonReader, default: YearMonth): YearMonth = in.readYearMonth(default)
@inline
override def encodeValue(x: YearMonth, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: YearMonth = null
}, "YearMonth")
implicit val yearC3C: Codec[Year] = new ShortAsciiStringCodec(new JsonValueCodec[Year] {
@inline
override def decodeValue(in: JsonReader, default: Year): Year = in.readYear(default)
@inline
override def encodeValue(x: Year, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: Year = null
}, "Year")
implicit val zonedDateTimeC3C: Codec[ZonedDateTime] = new ShortAsciiStringCodec(new JsonValueCodec[ZonedDateTime] {
@inline
override def decodeValue(in: JsonReader, default: ZonedDateTime): ZonedDateTime = in.readZonedDateTime(default)
@inline
override def encodeValue(x: ZonedDateTime, out: JsonWriter): Unit = out.writeVal(x)
@inline
override def nullValue: ZonedDateTime = null
}, "ZonedDateTime")
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy