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

mess.Encoder.scala Maven / Gradle / Ivy

The newest version!
package mess

import export._
import mess.ast.MsgPack

import scala.annotation.tailrec
import scala.collection.mutable

trait Encoder[A] extends Serializable { self =>

  def apply(a: A): MsgPack

  final def contramap[B](f: B => A): Encoder[B] = new Encoder[B] {
    def apply(a: B): MsgPack = self(f(a))
  }

  final def map(f: MsgPack => MsgPack): Encoder[A] = new Encoder[A] {
    def apply(a: A): MsgPack = f(self(a))
  }
}

object Encoder extends LowPriorityEncoder with TupleEncoder {

  @inline def apply[A](implicit A: Encoder[A]): Encoder[A] = A

  final def instance[A](fa: A => MsgPack): Encoder[A] = new Encoder[A] {
    def apply(a: A): MsgPack = fa(a)
  }

  implicit final val encodeBoolean: Encoder[Boolean] = new Encoder[Boolean] {
    def apply(a: Boolean): MsgPack = MsgPack.fromBoolean(a)
  }

  implicit final val encodeBytes: Encoder[Array[Byte]] = Encoder.instance[Array[Byte]](MsgPack.fromBytes)

  implicit final val encodeByte: Encoder[Byte] = new Encoder[Byte] {
    def apply(a: Byte): MsgPack = MsgPack.fromByte(a)
  }

  implicit final val encodeShort: Encoder[Short] = new Encoder[Short] {
    def apply(a: Short): MsgPack = MsgPack.fromShort(a)
  }

  implicit final val encodeInt: Encoder[Int] = new Encoder[Int] {
    def apply(a: Int): MsgPack = MsgPack.fromInt(a)
  }

  implicit final val encodeLong: Encoder[Long] = new Encoder[Long] {
    def apply(a: Long): MsgPack = MsgPack.fromLong(a)
  }

  implicit final val encodeBigInt: Encoder[BigInt] = new Encoder[BigInt] {
    def apply(a: BigInt): MsgPack = MsgPack.fromBigInt(a)
  }

  implicit final val encodeDouble: Encoder[Double] = new Encoder[Double] {
    def apply(a: Double): MsgPack = MsgPack.fromDouble(a)
  }

  implicit final val encodeFloat: Encoder[Float] = new Encoder[Float] {
    def apply(a: Float): MsgPack = MsgPack.fromFloat(a)
  }

  implicit final val encodeChar: Encoder[Char] = new Encoder[Char] {
    def apply(a: Char): MsgPack = MsgPack.fromString(a.toString)
  }

  implicit final val encodeString: Encoder[String] = new Encoder[String] {
    def apply(a: String): MsgPack = MsgPack.fromString(a)
  }

  implicit final def encodeSymbol[K <: Symbol]: Encoder[K] = new Encoder[K] {
    def apply(a: K): MsgPack = MsgPack.fromString(a.name)
  }

  implicit final def encodeOption[A](implicit A: Encoder[A]): Encoder[Option[A]] = new Encoder[Option[A]] {
    def apply(a: Option[A]): MsgPack = a match {
      case Some(v) => A(v)
      case None    => MsgPack.nil
    }
  }

  implicit final def encodeSome[A](implicit A: Encoder[A]): Encoder[Some[A]] =
    A.contramap[Some[A]](_.get)

  implicit final val encodeNone: Encoder[None.type] = new Encoder[None.type] {
    def apply(a: None.type): MsgPack = MsgPack.nil
  }

  @tailrec private[this] def iterLoop[A](rem: Iterator[A], acc: mutable.Builder[MsgPack, Vector[MsgPack]])(
      implicit A: Encoder[A]): Vector[MsgPack] =
    if (!rem.hasNext) acc.result()
    else iterLoop(rem, acc += A(rem.next()))

  implicit final def encodeSeq[A: Encoder]: Encoder[Seq[A]] = new Encoder[Seq[A]] {
    def apply(a: Seq[A]): MsgPack = {
      MsgPack.fromVector(iterLoop(a.iterator, Vector.newBuilder))
    }
  }

  implicit final def encodeSet[A: Encoder]: Encoder[Set[A]] = new Encoder[Set[A]] {
    def apply(a: Set[A]): MsgPack = {
      MsgPack.fromVector(iterLoop(a.iterator, Vector.newBuilder))
    }
  }

  implicit final def encodeList[A: Encoder]: Encoder[List[A]] = new Encoder[List[A]] {
    def apply(a: List[A]): MsgPack = {
      MsgPack.fromVector(iterLoop(a.iterator, Vector.newBuilder))
    }
  }

  implicit final def encodeVector[A: Encoder]: Encoder[Vector[A]] = new Encoder[Vector[A]] {
    def apply(a: Vector[A]): MsgPack = {
      MsgPack.fromVector(iterLoop(a.iterator, Vector.newBuilder))
    }
  }

  @tailrec private[this] def mapLoop[K, V](it: Iterator[(K, V)],
                                           acc: mutable.Builder[(MsgPack, MsgPack), Seq[(MsgPack, MsgPack)]])(
      implicit
      encodeK: Encoder[K],
      encodeV: Encoder[V]): Seq[(MsgPack, MsgPack)] = {
    if (!it.hasNext) acc.result()
    else {
      val (k, v) = it.next()
      mapLoop(it, acc += encodeK(k) -> encodeV(v))
    }
  }

  implicit final def encodeMap[K: Encoder, V: Encoder]: Encoder[Map[K, V]] =
    new Encoder[Map[K, V]] {
      def apply(a: Map[K, V]): MsgPack =
        MsgPack.fromPairSeq(mapLoop(a.iterator, Seq.newBuilder))
    }
}

@imports[Encoder]
trait LowPriorityEncoder




© 2015 - 2024 Weber Informatics LLC | Privacy Policy