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

zio.schema.codec.MessagePackCodec.scala Maven / Gradle / Ivy

The newest version!
package zio.schema.codec

import java.math.{ BigInteger, MathContext }
import java.time._

import zio.schema.codec.DecodeError.ReadError
import zio.schema.{ Schema, StandardType }
import zio.stream.ZPipeline
import zio.{ Cause, Chunk, ZIO }

object MessagePackCodec {
  implicit def messagePackCodec[A](implicit schema: Schema[A]): BinaryCodec[A] =
    new BinaryCodec[A] {
      override def encode(a: A): Chunk[Byte] =
        new MessagePackEncoder().encode(schema, a)

      override def decode(bytes: Chunk[Byte]): Either[DecodeError, A] =
        if (bytes.isEmpty)
          Left(ReadError(Cause.empty, "No bytes to decode"))
        else
          decodeChunk(bytes)

      override def streamEncoder: ZPipeline[Any, Nothing, A, Byte] = {
        val encoder = new MessagePackEncoder()
        ZPipeline.mapChunks { chunk =>
          chunk.flatMap(encoder.encode(schema, _))
        }
      }

      override def streamDecoder: ZPipeline[Any, DecodeError, Byte, A] =
        ZPipeline.mapChunksZIO { chunk =>
          ZIO.fromEither(
            decodeChunk(chunk).map(Chunk(_))
          )
        }

      private def decodeChunk(chunk: Chunk[Byte]) =
        new MessagePackDecoder(chunk)
          .decode(schema)
          .left
          .map(identity)
    }

  //TODO those are duplicates from ThriftCodec
  val bigDecimalStructure: Seq[Schema.Field[java.math.BigDecimal, _]] =
    Seq(
      Schema.Field(
        "unscaled",
        Schema.Primitive(StandardType.BigIntegerType),
        get0 = _.unscaledValue(),
        set0 = (a, b: BigInteger) => new java.math.BigDecimal(b, a.scale)
      ),
      Schema.Field(
        "precision",
        Schema.Primitive(StandardType.IntType),
        get0 = _.precision(),
        set0 = (a, b: Int) => new java.math.BigDecimal(a.unscaledValue, new MathContext(b))
      ),
      Schema
        .Field("scale", Schema.Primitive(StandardType.IntType), get0 = _.scale(), set0 = (a, b: Int) => a.setScale(b))
    )

  val monthDayStructure: Seq[Schema.Field[MonthDay, Int]] =
    Seq(
      Schema.Field(
        "month",
        Schema.Primitive(StandardType.IntType),
        get0 = (v: MonthDay) => v.getMonthValue,
        set0 = (a, b: Int) => a.`with`(Month.of(b))
      ),
      Schema
        .Field(
          "day",
          Schema.Primitive(StandardType.IntType),
          get0 = _.getDayOfMonth,
          set0 = (a, b: Int) => a.withDayOfMonth(b)
        )
    )

  val periodStructure: Seq[Schema.Field[Period, Int]] = Seq(
    Schema
      .Field("years", Schema.Primitive(StandardType.IntType), get0 = _.getYears, set0 = (a, b: Int) => a.withYears(b)),
    Schema.Field(
      "months",
      Schema.Primitive(StandardType.IntType),
      get0 = _.getMonths,
      set0 = (a, b: Int) => a.withMonths(b)
    ),
    Schema.Field("days", Schema.Primitive(StandardType.IntType), get0 = _.getDays, set0 = (a, b: Int) => a.withDays(b))
  )

  val yearMonthStructure: Seq[Schema.Field[YearMonth, Int]] =
    Seq(
      Schema.Field(
        "year",
        Schema.Primitive(StandardType.IntType),
        get0 = _.getYear,
        set0 = (a, b: Int) => a.`with`(Year.of(b))
      ),
      Schema.Field(
        "month",
        Schema.Primitive(StandardType.IntType),
        get0 = _.getMonthValue,
        set0 = (a, b: Int) => a.`with`(Month.of(b))
      )
    )

  val durationStructure: Seq[Schema.Field[Duration, _]] =
    Seq(
      Schema.Field(
        "seconds",
        Schema.Primitive(StandardType.LongType),
        get0 = _.getSeconds,
        set0 = (a, b: Long) => a.plusSeconds(b)
      ),
      Schema
        .Field(
          "nanos",
          Schema.Primitive(StandardType.IntType),
          get0 = _.getNano,
          set0 = (a, b: Int) => a.plusNanos(b.toLong)
        )
    )
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy