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

izumi.thirdparty.internal.boopickle.CodecSpeed.scala Maven / Gradle / Ivy

package izumi.thirdparty.internal.boopickle

import java.nio.{ByteBuffer, ByteOrder}

private[izumi] class DecoderSpeed(val buf: ByteBuffer) extends Decoder {
  val stringCodec: StringCodecBase = StringCodec

  /**
    * Decodes a single byte
    *
    * @return
    */
  def readByte: Byte = {
    buf.get
  }

  /**
    * Decodes a character
    *
    * @return
    */
  def readChar: Char = {
    buf.getChar()
  }

  /**
    * Decodes a 16-bit integer
    */
  def readShort: Short = {
    buf.getShort
  }

  /**
    * Decodes a 32-bit integer
    */
  def readInt: Int = {
    buf.getInt
  }

  def readRawInt: Int = {
    buf.getInt
  }

  /**
    * Decodes a 64-bit integer
    */
  def readLong: Long = {
    buf.getLong
  }

  def readRawLong: Long = {
    buf.getLong
  }

  /**
    * Decodes a 32-bit integer, or a special code
    *
    * @return
    */
  def readIntCode: Either[Byte, Int] = {
    val b = buf.get & 0xFF
    if ((b & 0x80) != 0) {
      Left((b & 0xF).toByte)
    } else {
      Right(buf.getInt)
    }
  }

  /**
    * Decodes a 64-bit long, or a special code
    *
    * @return
    */
  def readLongCode: Either[Byte, Long] = {
    val b = buf.get & 0xFF
    if ((b & 0x80) != 0) {
      Left((b & 0xF).toByte)
    } else {
      Right(buf.getLong)
    }
  }

  /**
    * Decodes a 32-bit float (4 bytes)
    *
    * @return
    */
  def readFloat: Float = {
    buf.getFloat
  }

  /**
    * Decodes a 64-bit double (8 bytes)
    *
    * @return
    */
  def readDouble: Double = {
    buf.getDouble
  }

  /**
    * Decodes a UTF-8 encoded string
    *
    * @return
    */
  def readString: String = readString(readInt)

  /**
    * Decodes a UTF-8 encoded string whose length is already known
    *
    * @param len Length of the string (in bytes)
    * @return
    */
  def readString(len: Int): String = {
    stringCodec.decodeFast(len, buf)
  }

  def readByteBuffer: ByteBuffer = {
    // length and byte order are encoded into same integer
    val sizeBO = readInt
    if (sizeBO < 0)
      throw new IllegalArgumentException(s"Invalid size $sizeBO for ByteBuffer")
    val size      = sizeBO >> 1
    val byteOrder = if ((sizeBO & 1) == 1) ByteOrder.BIG_ENDIAN else ByteOrder.LITTLE_ENDIAN
    // create a copy (sharing content), set correct byte order
    val b = buf.slice().order(byteOrder)
    (buf: java.nio.Buffer).position(buf.position() + size)
    (b: java.nio.Buffer).limit(b.position() + size)
    b
  }

  /**
    * Decodes an array of Bytes
    */
  def readByteArray(): Array[Byte] = readByteArray(readRawInt)
  def readByteArray(len: Int): Array[Byte] = {
    val array = new Array[Byte](len)
    buf.get(array)
    array
  }

  /**
    * Decodes an array of Integers
    */
  def readIntArray(): Array[Int] = readIntArray(readRawInt)
  def readIntArray(len: Int): Array[Int] = {
    val array = new Array[Int](len)
    buf.asIntBuffer().get(array)
    (buf: java.nio.Buffer).position(buf.position() + len * 4)
    array
  }

  /**
    * Decodes an array of Floats
    */
  def readFloatArray(): Array[Float] = readFloatArray(readRawInt)
  def readFloatArray(len: Int): Array[Float] = {
    val array = new Array[Float](len)
    buf.asFloatBuffer().get(array)
    (buf: java.nio.Buffer).position(buf.position() + len * 4)
    array
  }

  /**
    * Decodes an array of Doubles
    */
  def readDoubleArray(): Array[Double] = {
    val len = readRawInt
    readRawInt // remove padding
    readDoubleArray(len)
  }
  def readDoubleArray(len: Int): Array[Double] = {
    val array = new Array[Double](len)
    buf.asDoubleBuffer().get(array)
    (buf: java.nio.Buffer).position(buf.position() + len * 8)
    array
  }
}

private[izumi] class EncoderSpeed(bufferProvider: BufferProvider = DefaultByteBufferProvider.provider) extends Encoder {
  val stringCodec: StringCodecBase = StringCodec

  @inline private def alloc(size: Int): ByteBuffer = bufferProvider.alloc(size)

  /**
    * Encodes a single byte
    *
    * @param b Byte to encode
    * @return
    */
  def writeByte(b: Byte): Encoder = {
    alloc(1).put(b)
    this
  }

  /**
    * Encodes a single character using UTF-8 encoding
    *
    * @param c Character to encode
    * @return
    */
  def writeChar(c: Char): Encoder = {
    alloc(2).putChar(c)
    this
  }

  /**
    * Encodes a short integer
    */
  def writeShort(s: Short): Encoder = {
    alloc(2).putShort(s)
    this
  }

  /**
    * Encodes an integer
    *
    * @param i Integer to encode
    */
  def writeInt(i: Int): Encoder = {
    alloc(4).putInt(i)
    this
  }

  /**
    * Encodes an integer in 32-bits
    *
    * @param i Integer to encode
    * @return
    */
  def writeRawInt(i: Int): Encoder = {
    alloc(4).putInt(i)
    this
  }

  /**
    * Encodes a long
    *
    * @param l Long to encode
    */
  def writeLong(l: Long): Encoder = {
    alloc(8).putLong(l)
    this
  }

  /**
    * Encodes a long in 64-bits
    *
    * @param l Long to encode
    * @return
    */
  def writeRawLong(l: Long): Encoder = {
    alloc(8).putLong(l)
    this
  }

  /**
    * Writes either a code byte (0-15) or an Int
    *
    * @param intCode Integer or a code byte
    */
  def writeIntCode(intCode: Either[Byte, Int]): Encoder = {
    intCode match {
      case Left(code) =>
        alloc(1).put((code | 0x80).toByte)
      case Right(i) =>
        alloc(5).put(0.toByte).putInt(i)
    }
    this
  }

  /**
    * Writes either a code byte (0-15) or a Long
    *
    * @param longCode Long or a code byte
    */
  def writeLongCode(longCode: Either[Byte, Long]): Encoder = {
    longCode match {
      case Left(code) =>
        alloc(1).put((code | 0x80).toByte)
      case Right(l) =>
        alloc(9).put(0.toByte).putLong(l)
    }
    this
  }

  /**
    * Encodes a string using UTF8
    *
    * @param s String to encode
    * @return
    */
  def writeString(s: String): Encoder = {
    writeInt(s.length)
    val bb = alloc(s.length * 3)
    stringCodec.encodeFast(s, bb)
    this
  }

  /**
    * Encodes a float as 4 bytes
    *
    * @param f Float to encode
    * @return
    */
  def writeFloat(f: Float): Encoder = {
    alloc(4).putFloat(f)
    this
  }

  /**
    * Encodes a double as 8 bytes
    *
    * @param d Double to encode
    * @return
    */
  def writeDouble(d: Double): Encoder = {
    alloc(8).putDouble(d)
    this
  }

  /**
    * Encodes a ByteBuffer by writing its length and content
    *
    * @param bb ByteBuffer to encode
    * @return
    */
  def writeByteBuffer(bb: ByteBuffer): Encoder = {
    bb.mark()
    val byteOrder = if (bb.order() == ByteOrder.BIG_ENDIAN) 1 else 0
    // encode byte order as bit 0 in the length
    writeInt(bb.remaining * 2 | byteOrder)
    alloc(bb.remaining).put(bb)
    (bb: java.nio.Buffer).reset()
    this
  }

  /**
    * Encodes an array of Bytes
    */
  def writeByteArray(ba: Array[Byte]): Encoder = {
    writeRawInt(ba.length)
    alloc(ba.length).put(ba)
    this
  }

  /**
    * Encodes an array of Integers
    */
  def writeIntArray(ia: Array[Int]): Encoder = {
    writeRawInt(ia.length)
    val bb = alloc(ia.length * 4)
    bb.asIntBuffer().put(ia)
    (bb: java.nio.Buffer).position(bb.position() + ia.length * 4)
    this
  }

  /**
    * Encodes an array of Floats
    */
  def writeFloatArray(fa: Array[Float]): Encoder = {
    writeRawInt(fa.length)
    val bb = alloc(fa.length * 4)
    bb.asFloatBuffer().put(fa)
    (bb: java.nio.Buffer).position(bb.position() + fa.length * 4)
    this
  }

  /**
    * Encodes an array of Doubles
    */
  def writeDoubleArray(da: Array[Double]): Encoder = {
    writeRawInt(da.length)
    // padding
    writeRawInt(0)
    val bb = alloc(da.length * 8)
    bb.asDoubleBuffer().put(da)
    (bb: java.nio.Buffer).position(bb.position() + da.length * 8)
    this
  }

  /**
    * Completes the encoding and returns the ByteBuffer
    *
    * @return
    */
  def asByteBuffer = bufferProvider.asByteBuffer

  /**
    * Completes the encoding and returns a sequence of ByteBuffers
    *
    * @return
    */
  def asByteBuffers = bufferProvider.asByteBuffers
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy