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

ch.epfl.scala.debugadapter.internal.scalasig.ScalaSigReader.scala Maven / Gradle / Ivy

package ch.epfl.scala.debugadapter.internal.scalasig

import java.nio.charset.StandardCharsets

/**
 * Originally copied from https://github.com/JetBrains/intellij-scala
 * https://github.com/JetBrains/intellij-scala/blob/074e8f98d9789b3e7def3ade8d39e7ae770beccf/scala/decompiler/src/org/jetbrains/plugins/scala/decompiler/scalasig/ScalaSigReader.scala
 *
 * Nikolay.Tropin
 * 19-Jul-17
 */

//Based on scala.reflect.internal.pickling.PickleBuffer
class ScalaSigReader(bytes: Array[Byte]) {
  var readIndex = 0

  skipVersion()

  /** Read a byte */
  def readByte(): Int = {
    val x = bytes(readIndex).toInt; readIndex += 1; x
  }

  /**
   * Read a natural number in big endian format, base 128.
   *  All but the last digits have bit 0x80 set.
   */
  def readNat(): Int = readLongNat().toInt

  def readLongNat(): Long = {
    var b = 0L
    var x = 0L
    def next(): Unit = {
      b = readByte().toLong
      x = (x << 7) + (b & 0x7f)
    }

    next()
    while ((b & 0x80) != 0L) next()
    x
  }

  /** Read a long number in signed big endian format, base 256. */
  def readLong(len: Int): Long = {
    var x = 0L
    var i = 0
    while (i < len) {
      x = (x << 8) + (readByte() & 0xff)
      i += 1
    }
    val leading = 64 - (len << 3)
    x << leading >> leading
  }

  def readUtf8(length: Int): String = {
    val savedIndex = readIndex
    readIndex += length
    new String(bytes, savedIndex, length, StandardCharsets.UTF_8)
  }

  def until[T](end: Int, op: () => T): List[T] = {
    if (readIndex >= end) List()
    else {
      val startIdx = readIndex
      val result = op()

      if (startIdx == readIndex) List()
      else result :: until(end, op)
    }
  }

  /**
   * Pickle = majorVersion_Nat minorVersion_Nat nbEntries_Nat {Entry}
   *  Entry  = type_Nat length_Nat [actual entries]
   *
   *  Assumes that the ..Version_Nat are already consumed.
   *
   *  @return an array mapping entry numbers to locations in
   *  the byte array where the entries start.
   */
  def createIndex(): Array[Int] = {
    val size = readNat()
    val index = new Array[Int](size) // nbEntries_Nat
    var i = 0
    while (i < size) {
      index(i) = readIndex
      readByte() // skip type_Nat
      readIndex = readNat() + readIndex // read length_Nat, jump to next entry
      i += 1
    }
    index
  }

  private def skipVersion(): Unit = {
    val major = readNat()
    val minor = readNat()
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy