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

msgpack4z.MsgInBuffer.scala Maven / Gradle / Ivy

package msgpack4z

import java.io.{ByteArrayInputStream, EOFException}
import java.math.BigInteger

object MsgInBuffer {
  def apply(bytes: Array[Byte]): MsgInBuffer =
    new MsgInBuffer(new ByteArrayInputStream(bytes))
}

final class MsgInBuffer(buf: ByteArrayInputStream) extends MsgUnpacker {

  def skipBytes(n: Int): Unit = {
    buf.skip(n)
  }

  private[this] def readByte(): Byte = {
    val b = buf.read()
    if (b < 0) {
      throw new EOFException()
    } else {
      b.asInstanceOf[Byte]
    }
  }

  private[this] def readShort(): Short = {
    val ch1, ch2 = buf.read()
    if ((ch1 | ch2) < 0) {
      throw new EOFException()
    } else {
      ((ch1 << 8) + ch2).asInstanceOf[Short]
    }
  }

  private[this] def readInt(): Int = {
    val ch1, ch2, ch3, ch4 = buf.read()
    if ((ch1 | ch2 | ch3 | ch4) < 0) {
      throw new EOFException()
    } else {
      (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4
    }
  }

  private[this] def readLong(): Long = {
    val ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8 = buf.read().asInstanceOf[Long]
    if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) {
      throw new EOFException()
    } else {
      (ch1 << 56) + (ch2 << 48) + (ch3 << 40) + (ch4 << 32) + (ch5 << 24) + (ch6 << 16) + (ch7 << 8) + ch8
    }
  }

  private[this] def readFloat(): Float =
    java.lang.Float.intBitsToFloat(readInt())

  private[this] def readDouble(): Double =
    java.lang.Double.longBitsToDouble(readLong())

  /**
   * @return true if success
   */
  def unpackNilWithCheck(): Boolean = {
    readByte() == Code.NIL
  }

  def unpackBooleanOpt(): OptBool = {
    readByte() match {
      case Code.TRUE =>
        OptBool.True
      case Code.FALSE =>
        OptBool.False
      case _ =>
        OptBool.Empty
    }
  }

  def unpackByteOpt(): OptByte = {
    val b = readByte()
    if (Code.isFixInt(b)) {
      OptByte(b)
    } else {
      b match {
        case Code.UINT8 =>
          val u8 = readByte()
          if (u8 < 0) {
            OptByte.empty
          } else {
            OptByte(u8)
          }
        case Code.UINT16 =>
          val u16 = readShort()
          if (u16 < 0 || u16 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(u16.asInstanceOf[Byte])
          }
        case Code.UINT32 =>
          val u32 = readInt()
          if (u32 < 0 || u32 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(u32.asInstanceOf[Byte])
          }
        case Code.UINT64 =>
          val u64 = readLong()
          if (u64 < 0L || u64 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(u64.asInstanceOf[Byte])
          }
        case Code.INT8 =>
          OptByte(readByte())
        case Code.INT16 =>
          val i16 = readShort()
          if (i16 < Byte.MinValue || i16 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(i16.asInstanceOf[Byte])
          }
        case Code.INT32 =>
          val i32 = readInt()
          if (i32 < Byte.MinValue || i32 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(i32.asInstanceOf[Byte])
          }
        case Code.INT64 =>
          val i64 = readLong()
          if (i64 < Byte.MinValue || i64 > Byte.MaxValue) {
            OptByte.empty
          } else {
            OptByte(i64.asInstanceOf[Byte])
          }
        case _ =>
          OptByte.empty
      }
    }
  }

  def unpackShortOpt(): OptShort = {
    val b = readByte()
    if (Code.isFixInt(b)) {
      OptShort(b)
    } else {
      b match {
        case Code.UINT8 =>
          val u8 = readByte()
          OptShort((u8 & 0xff).asInstanceOf[Short])
        case Code.UINT16 =>
          val u16 = readShort()
          if (u16 < 0) {
            OptShort.empty
          } else {
            OptShort(u16)
          }
        case Code.UINT32 =>
          val u32 = readInt()
          if (u32 < 0 || u32 > Short.MaxValue) {
            OptShort.empty
          } else {
            OptShort(u32.asInstanceOf[Short])
          }
        case Code.UINT64 =>
          val u64 = readLong()
          if (u64 < 0L || u64 > Short.MaxValue) {
            OptShort.empty
          } else {
            OptShort(u64.asInstanceOf[Short])
          }
        case Code.INT8 =>
          val i8 = readByte()
          OptShort(i8.asInstanceOf[Short])
        case Code.INT16 =>
          OptShort(readShort())
        case Code.INT32 =>
          val i32 = readInt()
          if (i32 < Short.MinValue || i32 > Short.MaxValue) {
            OptShort.empty
          } else {
            OptShort(i32.asInstanceOf[Short])
          }
        case Code.INT64 =>
          val i64 = readLong()
          if (i64 < Short.MinValue || i64 > Short.MaxValue) {
            OptShort.empty
          } else {
            OptShort(i64.asInstanceOf[Short])
          }
        case _ =>
          OptShort.empty
      }
    }
  }

  def unpackIntOpt(): OptInt = {
    val b = readByte()
    if (Code.isFixInt(b)) {
      OptInt(b)
    } else {
      b match {
        case Code.UINT8 =>
          val u8 = readByte()
          OptInt(u8 & 0xff)
        case Code.UINT16 =>
          val u16 = readShort()
          OptInt(u16 & 0xffff)
        case Code.UINT32 =>
          val u32 = readInt()
          if (u32 < 0) {
            OptInt.empty
          } else {
            OptInt(u32)
          }
        case Code.UINT64 =>
          val u64 = readLong()
          if (u64 < 0L || u64 > Int.MaxValue) {
            OptInt.empty
          } else {
            OptInt(u64.asInstanceOf[Int])
          }
        case Code.INT8 =>
          OptInt(readByte())
        case Code.INT16 =>
          OptInt(readShort())
        case Code.INT32 =>
          OptInt(readInt())
        case Code.INT64 =>
          val i64 = readLong()
          if (i64 < Int.MinValue || i64 > Int.MaxValue) {
            OptInt.empty
          } else {
            OptInt(i64.asInstanceOf[Int])
          }
        case _ =>
          OptInt.empty
      }
    }
  }

  override def unpackLong(): Long = {
    val b = readByte()
    if (Code.isFixInt(b)) {
      b
    } else {
      b match {
        case Code.UINT8 =>
          val u8 = readByte()
          u8 & 0xff
        case Code.UINT16 =>
          val u16 = readShort()
          u16 & 0xffff
        case Code.UINT32 =>
          val u32 = readInt()
          if (u32 < 0) {
            (u32 & 0x7fffffff) + 0x80000000L
          } else {
            u32
          }
        case Code.UINT64 =>
          val u64 = readLong()
          if (u64 < 0L) {
            throw new RuntimeException("overflow " + u64)
          }
          u64
        case Code.INT8 =>
          readByte()
        case Code.INT16 =>
          readShort()
        case Code.INT32 =>
          readInt()
        case Code.INT64 =>
          readLong()
      }
    }
  }

  override def unpackBigInteger(): BigInteger = {
    val b = readByte()
    if (Code.isFixInt(b)) {
      BigInteger.valueOf(b)
    } else {
      b match {
        case Code.UINT8 =>
          val u8 = readByte()
          BigInteger.valueOf(u8 & 0xff)
        case Code.UINT16 =>
          val u16 = readShort()
          BigInteger.valueOf(u16 & 0xffff)
        case Code.UINT32 =>
          val u32 = readInt()
          if (u32 < 0) {
            BigInteger.valueOf((u32 & 0x7fffffff) + 0x80000000L)
          } else {
            BigInteger.valueOf(u32)
          }
        case Code.UINT64 =>
          val u64 = readLong()
          if (u64 < 0L) {
            BigInteger.valueOf(u64 + Long.MaxValue + 1L).setBit(63)
          } else {
            BigInteger.valueOf(u64)
          }
        case Code.INT8 =>
          val i8 = readByte()
          BigInteger.valueOf(i8)
        case Code.INT16 =>
          val i16 = readShort()
          BigInteger.valueOf(i16)
        case Code.INT32 =>
          val i32 = readInt()
          BigInteger.valueOf(i32)
        case Code.INT64 =>
          BigInteger.valueOf(readLong())
      }
    }
  }

  override def unpackFloat(): Float = {
    val b = readByte()
    b match {
      case Code.FLOAT32 =>
        readFloat()
      case Code.FLOAT64 =>
        readDouble().asInstanceOf[Float]
    }
  }

  override def unpackDouble(): Double = {
    val b = readByte()
    b match {
      case Code.FLOAT32 =>
        readFloat()
      case Code.FLOAT64 =>
        readDouble()
    }
  }

  def unpackArrayHeaderOpt(): OptInt = {
    val b = readByte()
    if (Code.isFixedArray(b)) {
      OptInt(b & 0x0f)
    } else {
      b match {
        case Code.ARRAY16 =>
          OptInt(readNextLength16())
        case Code.ARRAY32 =>
          OptInt(readInt())
        case _ =>
          OptInt.empty
      }
    }
  }

  def unpackMapHeaderOpt(): OptInt = {
    val b = readByte()
    if (Code.isFixedMap(b)) {
      OptInt(b & 0x0f)
    } else {
      b match {
        case Code.MAP16 =>
          OptInt(readNextLength16())
        case Code.MAP32 =>
          OptInt(readInt())
        case _ =>
          OptInt.empty
      }
    }
  }

  private def readStringHeader(b: Byte): OptInt = {
    b match {
      case Code.STR8 =>
        OptInt(readNextLength8())
      case Code.STR16 =>
        OptInt(readNextLength16())
      case Code.STR32 =>
        readNextLength32()
      case _ =>
        OptInt.empty
    }
  }

  def unpackRawStringHeader: OptInt = {
    val b = readByte()
    if (Code.isFixedRaw(b)) {
      OptInt(b & 0x1f)
    } else {
      readStringHeader(b)
    }
  }

  private[this] def readNextLength8(): Int =
    readByte() & 0xff

  private[this] def readNextLength16(): Int =
    readShort() & 0xffff

  private[this] def readNextLength32(): OptInt = {
    val u32 = readInt()
    if (u32 < 0) {
      OptInt.empty
    } else {
      OptInt(u32)
    }
  }

  override def close(): Unit = {
    buf.close()
  }

  override def nextType(): MsgType = {
    if (buf.markSupported()) {
      buf.mark(1024)
      try {
        Code.getType(readByte())
      } finally {
        buf.reset()
      }
    } else {
      sys.error("mark not supported")
    }
  }

  override def unpackBinary(): Array[Byte] = {
    val b = readByte()
    val len: Int =
      if (Code.isFixedRaw(b)) {
        0x1f & b
      } else {
        b match {
          case Code.BIN8 =>
            readNextLength8()
          case Code.BIN16 =>
            readNextLength16()
          case Code.BIN32 =>
            readNextLength32() match {
              case OptInt(l) =>
                l
              case _ =>
                sys.error("binary header length overflow")
            }
          case _ =>
            sys.error("not binary header " + b)
        }
      }
    val array = new Array[Byte](len)
    buf.read(array)
    array
  }

  override def mapEnd(): Unit = {
    // do nothing
  }

  override def unpackBoolean(): Boolean = {
    unpackBooleanOpt().get
  }

  override def unpackNil(): Unit = {
    assert(unpackNilWithCheck())
  }

  override def unpackString(): String = {
    val b = readByte()
    val len: Int =
      if (Code.isFixStr(b)) {
        0x1f & b
      } else {
        b match {
          case Code.STR8 =>
            readNextLength8()
          case Code.STR16 =>
            readNextLength16()
          case Code.STR32 =>
            readNextLength32().get
          case _ =>
            sys.error("not string header " + b)
        }
      }
    val array = new Array[Byte](len)
    buf.read(array)
    new String(array, "UTF-8")
  }

  override def arrayEnd(): Unit = {
    // do nothing
  }

  override def unpackByte(): Byte = {
    unpackByteOpt().get
  }

  override def unpackArrayHeader(): Int = {
    unpackArrayHeaderOpt().get
  }

  override def unpackInt(): Int = {
    unpackIntOpt().get
  }

  override def unpackShort(): Short = {
    unpackShortOpt().get
  }

  override def unpackMapHeader(): Int = {
    unpackMapHeaderOpt().get
  }

  override def readPayload(length: Int): Array[Byte] = {
    val array = new Array[Byte](length)
    buf.read(array)
    array
  }

  override def readPayload(a: Array[Byte]): Unit = {
    buf.read(a)
  }

  override def unpackExtTypeHeader(): ExtTypeHeader = {
    readByte() match {
      case Code.FIXEXT1 =>
        new ExtTypeHeader(readByte(), 1)
      case Code.FIXEXT2 =>
        new ExtTypeHeader(readByte(), 2)
      case Code.FIXEXT4 =>
        new ExtTypeHeader(readByte(), 4)
      case Code.FIXEXT8 =>
        new ExtTypeHeader(readByte(), 8)
      case Code.FIXEXT16 =>
        new ExtTypeHeader(readByte(), 16)
      case Code.EXT8 =>
        val length = readByte() & 0xff
        val tpe = readByte()
        new ExtTypeHeader(tpe, length)
      case Code.EXT16 =>
        val length = readShort() & 0xffff
        val tpe = readByte()
        new ExtTypeHeader(tpe, length)
      case Code.EXT32 =>
        val length = readInt()
        val tpe = readByte()
        new ExtTypeHeader(tpe, length)
      case other =>
        sys.error("unexpected type " + other)
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy