1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package dotty.tools.dotc
package core
package pickling
import scala.collection.mutable
import PickleFormat._
import Names.{Name, termName}
import java.util.UUID
object TastyUnpickler {
class UnpickleException(msg: String) extends Exception(msg)
abstract class SectionUnpickler[R](val name: String) {
def unpickle(reader: TastyReader, tastyName: TastyName.Table): R
}
}
import TastyUnpickler._
class TastyUnpickler(reader: TastyReader) {
import reader._
def this(bytes: Array[Byte]) = this(new TastyReader(bytes))
private val sectionReader = new mutable.HashMap[String, TastyReader]
val tastyName = new TastyName.Table
def check(cond: Boolean, msg: => String) =
if (!cond) throw new UnpickleException(msg)
def readString(): String = {
val TastyName.Simple(name) = tastyName(readNameRef())
name.toString
}
def readName(): TastyName = {
import TastyName._
val tag = readByte()
val length = readNat()
val start = currentAddr
val end = start + length
val result = tag match {
case UTF8 =>
goto(end)
Simple(termName(bytes, start.index, length))
case QUALIFIED =>
Qualified(readNameRef(), readNameRef())
case SIGNED =>
val original = readNameRef()
val result = readNameRef()
val params = until(end)(readNameRef())
Signed(original, params, result)
case EXPANDED =>
Expanded(readNameRef(), readNameRef())
case OBJECTCLASS =>
ModuleClass(readNameRef())
case SUPERACCESSOR =>
SuperAccessor(readNameRef())
case DEFAULTGETTER =>
DefaultGetter(readNameRef(), readNat())
case SHADOWED =>
Shadowed(readNameRef())
}
assert(currentAddr == end, s"bad name $result $start $currentAddr $end")
result
}
private def readHeader(): UUID = {
for (i <- 0 until header.length)
check(readByte() == header(i), "not a TASTy file")
val major = readNat()
val minor = readNat()
check(major == MajorVersion && minor <= MinorVersion,
s"""TASTy signature has wrong version.
| expected: $MajorVersion.$MinorVersion
| found : $major.$minor""".stripMargin)
new UUID(readUncompressedLong(), readUncompressedLong())
}
val uuid = readHeader()
locally {
until(readEnd()) { tastyName.add(readName()) }
while (!isAtEnd) {
val secName = readString()
val secEnd = readEnd()
sectionReader(secName) = new TastyReader(bytes, currentAddr.index, secEnd.index, currentAddr.index)
goto(secEnd)
}
}
def unpickle[R](sec: SectionUnpickler[R]): Option[R] =
for (reader <- sectionReader.get(sec.name)) yield
sec.unpickle(reader, tastyName)
}
|