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

upack.MsgPackReader.scala Maven / Gradle / Ivy

The newest version!
package upack
import upickle.core.{BufferingInputStreamParser, Visitor}
import upack.{MsgPackKeys => MPK}

import scala.annotation.switch

class MsgPackReader(input0: Array[Byte]) extends BaseMsgPackReader {
  val srcLength = input0.length
  protected[this] final def close() = {}

  // Make sure we never call this method, since it will mutate the original array,
  // and it should not be necessary to call it if our implementation is correct.
  override def growBuffer(until: Int): Unit = ???

  def readDataIntoBuffer(buffer: Array[Byte], bufferOffset: Int) = {
    if(buffer == null) (input0, false, srcLength)
    else (input0, true, -1)
  }
}

class InputStreamMsgPackReader(val inputStream: java.io.InputStream,
                               val minBufferStartSize: Int = BufferingInputStreamParser.defaultMinBufferStartSize,
                               val maxBufferStartSize: Int = BufferingInputStreamParser.defaultMaxBufferStartSize)
extends BaseMsgPackReader with upickle.core.BufferingInputStreamParser{
}

abstract class BaseMsgPackReader extends upickle.core.BufferingByteParser{

  private[this] var index = 0
  def getIndex = index
  def parse[T](visitor: Visitor[_, T]): T = {

    val n = getByteSafe(index)
    (n & 0xFF: @switch) match{
      case MPK.Nil => index += 1; visitor.visitNull(index)
      case MPK.False => index += 1; visitor.visitFalse(index)
      case MPK.True => index += 1; visitor.visitTrue(index)

      case MPK.Bin8 => parseBin(parseUInt8(index + 1), visitor)
      case MPK.Bin16 => parseBin(parseUInt16(index + 1), visitor)
      case MPK.Bin32 => parseBin(parseUInt32(index + 1), visitor)

      case MPK.Ext8 => parseExt(parseUInt8(index + 1), visitor)
      case MPK.Ext16 => parseExt(parseUInt16(index + 1), visitor)
      case MPK.Ext32 => parseExt(parseUInt32(index + 1), visitor)

      case MPK.Float32 => visitor.visitFloat64(java.lang.Float.intBitsToFloat(parseUInt32(index + 1)), index)
      case MPK.Float64 => visitor.visitFloat64(java.lang.Double.longBitsToDouble(parseUInt64(index + 1)), index)

      case MPK.UInt8 => visitor.visitInt32(parseUInt8(index + 1), index)
      case MPK.UInt16 => visitor.visitInt32(parseUInt16(index + 1), index)
      case MPK.UInt32 => visitor.visitInt64(parseUInt32(index + 1) & 0xffffffffL, index)
      case MPK.UInt64 => visitor.visitUInt64(parseUInt64(index + 1), index)

      case MPK.Int8 => visitor.visitInt32(parseUInt8(index + 1).toByte, index)
      case MPK.Int16 => visitor.visitInt32(parseUInt16(index + 1).toShort, index)
      case MPK.Int32 => visitor.visitInt32(parseUInt32(index + 1), index)
      case MPK.Int64 => visitor.visitInt64(parseUInt64(index + 1), index)

      case MPK.FixExt1 => index += 1; parseExt(1, visitor)
      case MPK.FixExt2 => index += 1; parseExt(2, visitor)
      case MPK.FixExt4 => index += 1; parseExt(4, visitor)
      case MPK.FixExt8 => index += 1; parseExt(8, visitor)
      case MPK.FixExt16 => index += 1; parseExt(16, visitor)

      case MPK.Str8 => parseStr(parseUInt8(index + 1), visitor)
      case MPK.Str16 => parseStr(parseUInt16(index + 1), visitor)
      case MPK.Str32 => parseStr(parseUInt32(index + 1), visitor)

      case MPK.Array16 => parseArray(parseUInt16(index + 1), visitor)
      case MPK.Array32 => parseArray(parseUInt32(index + 1), visitor)

      case MPK.Map16 => parseMap(parseUInt16(index + 1), visitor)
      case MPK.Map32 => parseMap(parseUInt32(index + 1), visitor)
      case x =>
        if (x <= MPK.PositiveFixInt) {
          // positive fixint
          index += 1
          visitor.visitInt32(x & 0x7f, index)
        } else if (x <= MPK.FixMap) {
          val n = x & 0x0f
          index += 1
          parseMap (n, visitor)
        } else if (x <= MPK.FixArray) {
          val n = x & 0x0f
          index += 1
          parseArray (n, visitor)
        }
          else if (x <= MPK.FixStr ) {
          val n = x & 0x1f
          index += 1
          parseStr(n, visitor)
        } else if (x >= 0xe0) { // negative fixint
          index += 1
          visitor.visitInt32(x | 0xffffffe0, index)
        } else ???
    }
  }
  def parseExt[T](n: Int, visitor: Visitor[_, T]) = {
    val (arr, i, j) = sliceArr(index + 1, n)
    val res = visitor.visitExt(getByteSafe(index), arr, i, j, index)
    index += n + 1
    res
  }

  def parseStr[T](n: Int, visitor: Visitor[_, T]) = {
    val res = visitor.visitString(sliceString(index, index + n), index)
    index += n
    res
  }
  def parseBin[T](n: Int, visitor: Visitor[_, T]) = {
    val (arr, i, j) = sliceArr(index, n)
    val res = visitor.visitBinary(arr, i, j, index)
    index += n
    res
  }
  def parseMap[T](n: Int, visitor: Visitor[_, T]) = {
    val obj = visitor.visitObject(n, true, index)

    var i = 0
    while(i < n){
      val keyVisitor = obj.visitKey(index)
      obj.visitKeyValue(parse(keyVisitor.asInstanceOf[Visitor[_, T]]))
      obj.narrow.visitValue(parse(obj.subVisitor.asInstanceOf[Visitor[_, T]]), index)
      dropBufferUntil(index)
      i += 1
    }
    obj.visitEnd(index)
  }
  def parseArray[T](n: Int, visitor: Visitor[_, T]) = {
    val arr = visitor.visitArray(n, index)

    var i = 0

    while(i < n){
      val v = parse(arr.subVisitor.asInstanceOf[Visitor[_, T]])
      arr.narrow.visitValue(v, index)
      dropBufferUntil(index)
      i += 1
    }
    arr.visitEnd(index)
  }
  def parseUInt8(i: Int) = {
    index = i + 1
    getByteSafe(i) & 0xff
  }
  def parseUInt16(i: Int) = {
    index = i + 2
    requestUntil(i + 1)
    (getByteUnsafe(i) & 0xff) << 8 | getByteUnsafe(i + 1) & 0xff
  }
  def parseUInt32(i: Int) = {
    index = i + 4
    requestUntil(i + 3)
    (getByteUnsafe(i) & 0xff) << 24 | (getByteUnsafe(i + 1) & 0xff) << 16 |
    (getByteUnsafe(i + 2) & 0xff) << 8 | getByteUnsafe(i + 3) & 0xff
  }
  def parseUInt64(i: Int) = {
    index = i + 8
    requestUntil(i + 7)
    (getByteUnsafe(i + 0).toLong & 0xff) << 56 | (getByteUnsafe(i + 1).toLong & 0xff) << 48 |
    (getByteUnsafe(i + 2).toLong & 0xff) << 40 | (getByteUnsafe(i + 3).toLong & 0xff) << 32 |
    (getByteUnsafe(i + 4).toLong & 0xff) << 24 | (getByteUnsafe(i + 5).toLong & 0xff) << 16 |
    (getByteUnsafe(i + 6).toLong & 0xff) << 8 | (getByteUnsafe(i + 7).toLong & 0xff) << 0
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy