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

zeroformatter.LazyList.scala Maven / Gradle / Ivy

package zeroformatter

final case class LazyList[F[_], A: Formatter](private val list: Vector[F[A]]) {

  val toVector: Vector[F[A]] = list

  val toList: List[F[A]] = list.toList
}

object LazyList {

  implicit def lazyListFormatter[F[_], A: Formatter](implicit
    F: Formatter[F[A]]
  ): Formatter[LazyList[F, A]] = new Formatter[LazyList[F, A]] {

    override val length = None

    override def serialize(encoder: Encoder, offset: Int, value: LazyList[F, A]) = {
      F.length match {
        case Some(_) => Formatter[Vector[F[A]]].serialize(encoder, offset, value.toVector)
        case None =>
          val v = value.toVector
          val len = v.length
          var byteSize = 4 + 4 + 4 * len
          encoder.ensureCapacity(offset, byteSize)
          var i = 0
          while(i < len) {
            encoder.writeIntUnsafe(offset + 4 + 4 + 4 * i, offset + byteSize)
            byteSize += F.serialize(encoder, offset + byteSize, v(i))
            i += 1
          }
          encoder.writeIntUnsafe(offset, byteSize)
          encoder.writeIntUnsafe(offset + 4, len)
          byteSize
      }
    }

    override def deserialize(decoder: Decoder) =
      F.length match {
        case Some(s) =>
          val len = decoder.readInt()
          if(len == -1) null.asInstanceOf[LazyList[F, A]]
          else if(len < -1) throw new FormatException(decoder.offset - 4, s"Invalid length($len).")
          else {
            var i = 0
            val builder = Vector.newBuilder[F[A]]
            while(i < len) {
              builder += F.deserialize(decoder)
              i += 1
              decoder.offset += s
            }
            LazyList(builder.result())
          }
        case None =>
          val start = decoder.offset
          val bs = decoder.readInt()
          if(bs == -1) null.asInstanceOf[LazyList[F, A]]
          else if(bs < -1) throw new FormatException(decoder.offset - 4, s"Invalid byte size($bs).")
          else {
            val l = decoder.readInt()
            val s = decoder.offset
            val builder = Vector.newBuilder[F[A]]
            var i = 0
            while(i < l) {
              decoder.offset = decoder.readInt(s + i * 4)
              builder += F.deserialize(decoder)
              i += 1
            }
            decoder.offset = start + bs
            LazyList(builder.result())
          }
      }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy