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

msgpack4z.ScalazCodec.scala Maven / Gradle / Ivy

package msgpack4z

import scalaz._

trait ScalazCodec {
  implicit def iListCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[IList[A]]
  implicit def imapCodec[A, B](implicit O: Order[A], A: MsgpackCodec[A], B: MsgpackCodec[B]): MsgpackCodec[A ==>> B]
  implicit def isetCodec[A](implicit O: Order[A], A: MsgpackCodec[A]): MsgpackCodec[ISet[A]]
  implicit def nonEmptyListCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[NonEmptyList[A]]
  implicit def maybeCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[Maybe[A]]
}

private[msgpack4z] trait ScalazCodecImpl extends ScalazCodec {
  override final def iListCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[IList[A]] =
    MsgpackCodec.tryE(
      (packer, list) => {
        packer.packArrayHeader(list.length)
        @annotation.tailrec
        def loop(x: IList[A]): Unit =
          x match {
            case ICons(h, t) =>
              A.pack(packer, h)
              loop(t)
            case _ =>
          }
        loop(list)
        packer.arrayEnd()
      },
      unpacker => {
        val size = unpacker.unpackArrayHeader()
        var list: IList[A] = INil()
        var i = 0
        var error: UnpackError \/ IList[A] = null
        while (i < size && error == null) {
          A.unpack(unpacker) match {
            case \/-(a) =>
              list ::= a
            case e @ -\/(_) =>
              error = e.coerceRight
          }
          i += 1
        }
        unpacker.arrayEnd()
        if (error == null)
          \/-(list.reverse)
        else
          error
      }
    )

  override final def isetCodec[A](implicit O: Order[A], A: MsgpackCodec[A]): MsgpackCodec[ISet[A]] =
    MsgpackCodec.tryE(
      (packer, set) => {
        packer.packArrayHeader(set.size)
        set.foldLeft(())((_, a) => A.pack(packer, a))
        packer.arrayEnd()
      },
      unpacker => {
        val size = unpacker.unpackArrayHeader()
        var set = ISet.empty[A]
        var i = 0
        var error: UnpackError \/ ISet[A] = null
        while (i < size && error == null) {
          A.unpack(unpacker) match {
            case \/-(a) =>
              set = set.insert(a)
            case e @ -\/(_) =>
              error = e.coerceRight
          }
          i += 1
        }
        unpacker.arrayEnd()
        if (error == null)
          \/-(set)
        else
          error
      }
    )

  override final def imapCodec[A, B](implicit O: Order[A], A: MsgpackCodec[A], B: MsgpackCodec[B]): MsgpackCodec[A ==>> B] = {
    MsgpackCodec.tryE(
      (packer, m) => {
        packer.packMapHeader(m.size)
        m.fold(()) { (key, value, _) =>
          A.pack(packer, key)
          B.pack(packer, value)
        }
        packer.mapEnd()
      },
      unpacker => {
        val size = unpacker.unpackMapHeader()
        var i = 0
        var error: UnpackError \/ (A ==>> B) = null
        var imap: A ==>> B = ==>>.empty
        while (i < size && error == null) {
          A.unpack(unpacker) match {
            case \/-(k) =>
              B.unpack(unpacker) match {
                case \/-(v) =>
                  imap = imap.insert(k, v)
                case e @ -\/(_) =>
                  error = e.coerceRight
              }
            case e @ -\/(_) =>
              error = e.coerceRight
          }
          i += 1
        }
        unpacker.mapEnd()
        if (error == null)
          \/-(imap)
        else
          error
      }
    )
  }

  override final def nonEmptyListCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[NonEmptyList[A]] =
    MsgpackCodec.tryE(
      (packer, nel) => {
        packer.packArrayHeader(nel.size)
        A.pack(packer, nel.head)
        @annotation.tailrec
        def loop(xs: IList[A]): Unit =
          xs match {
            case ICons(h, t) =>
              A.pack(packer, h)
              loop(t)
            case _ =>
          }
        loop(nel.tail)
        packer.arrayEnd()
      },
      unpacker => {
        val size = unpacker.unpackArrayHeader()
        if (size >= 1) {
          A.unpack(unpacker) match {
            case \/-(h) =>
              var list: IList[A] = IList.empty
              var i = 1
              var error: UnpackError \/ NonEmptyList[A] = null
              while (i < size && error == null) {
                A.unpack(unpacker) match {
                  case \/-(a) =>
                    list ::= a
                  case e @ -\/(_) =>
                    error = e.coerceRight
                }
                i += 1
              }
              unpacker.arrayEnd()
              if (error == null)
                \/-(NonEmptyList.nel(h, list.reverse))
              else
                error
            case e @ -\/(_) =>
              e.coerceRight
          }
        } else {
          -\/(NotEnoughArraySize(1, 0))
        }
      }
    )

  override final def maybeCodec[A](implicit A: MsgpackCodec[A]): MsgpackCodec[Maybe[A]] =
    MaybeCodec.maybeCompactCodec[A]
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy