1
2
3
4
5 package modindex
6
7 import (
8 "cmd/go/internal/base"
9 "encoding/binary"
10 "go/token"
11 "sort"
12 )
13
14 const indexVersion = "go index v2"
15
16
17
18 func encodeModuleBytes(packages []*rawPackage) []byte {
19 e := newEncoder()
20 e.Bytes([]byte(indexVersion + "\n"))
21 stringTableOffsetPos := e.Pos()
22 e.Uint32(0)
23 sort.Slice(packages, func(i, j int) bool {
24 return packages[i].dir < packages[j].dir
25 })
26 e.Int(len(packages))
27 packagesPos := e.Pos()
28 for _, p := range packages {
29 e.String(p.dir)
30 e.Int(0)
31 }
32 for i, p := range packages {
33 e.IntAt(e.Pos(), packagesPos+8*i+4)
34 encodePackage(e, p)
35 }
36 e.IntAt(e.Pos(), stringTableOffsetPos)
37 e.Bytes(e.stringTable)
38 e.Bytes([]byte{0xFF})
39 return e.b
40 }
41
42 func encodePackageBytes(p *rawPackage) []byte {
43 return encodeModuleBytes([]*rawPackage{p})
44 }
45
46 func encodePackage(e *encoder, p *rawPackage) {
47 e.String(p.error)
48 e.String(p.dir)
49 e.Int(len(p.sourceFiles))
50 sourceFileOffsetPos := e.Pos()
51 for range p.sourceFiles {
52 e.Int(0)
53 }
54 for i, f := range p.sourceFiles {
55 e.IntAt(e.Pos(), sourceFileOffsetPos+4*i)
56 encodeFile(e, f)
57 }
58 }
59
60 func encodeFile(e *encoder, f *rawFile) {
61 e.String(f.error)
62 e.String(f.parseError)
63 e.String(f.synopsis)
64 e.String(f.name)
65 e.String(f.pkgName)
66 e.Bool(f.ignoreFile)
67 e.Bool(f.binaryOnly)
68 e.String(f.cgoDirectives)
69 e.String(f.goBuildConstraint)
70
71 e.Int(len(f.plusBuildConstraints))
72 for _, s := range f.plusBuildConstraints {
73 e.String(s)
74 }
75
76 e.Int(len(f.imports))
77 for _, m := range f.imports {
78 e.String(m.path)
79 e.Position(m.position)
80 }
81
82 e.Int(len(f.embeds))
83 for _, embed := range f.embeds {
84 e.String(embed.pattern)
85 e.Position(embed.position)
86 }
87
88 e.Int(len(f.directives))
89 for _, d := range f.directives {
90 e.String(d.Text)
91 e.Position(d.Pos)
92 }
93 }
94
95 func newEncoder() *encoder {
96 e := &encoder{strings: make(map[string]int)}
97
98
99 e.stringTable = append(e.stringTable, 0)
100 e.strings[""] = 0
101
102 return e
103 }
104
105 func (e *encoder) Position(position token.Position) {
106 e.String(position.Filename)
107 e.Int(position.Offset)
108 e.Int(position.Line)
109 e.Int(position.Column)
110 }
111
112 type encoder struct {
113 b []byte
114 stringTable []byte
115 strings map[string]int
116 }
117
118 func (e *encoder) Pos() int {
119 return len(e.b)
120 }
121
122 func (e *encoder) Bytes(b []byte) {
123 e.b = append(e.b, b...)
124 }
125
126 func (e *encoder) String(s string) {
127 if n, ok := e.strings[s]; ok {
128 e.Int(n)
129 return
130 }
131 pos := len(e.stringTable)
132 e.strings[s] = pos
133 e.Int(pos)
134 e.stringTable = binary.AppendUvarint(e.stringTable, uint64(len(s)))
135 e.stringTable = append(e.stringTable, s...)
136 }
137
138 func (e *encoder) Bool(b bool) {
139 if b {
140 e.Uint32(1)
141 } else {
142 e.Uint32(0)
143 }
144 }
145
146 func (e *encoder) Uint32(n uint32) {
147 e.b = binary.LittleEndian.AppendUint32(e.b, n)
148 }
149
150
151
152 func (e *encoder) Int(n int) {
153 if n < 0 || int(int32(n)) != n {
154 base.Fatalf("go: attempting to write an int to the index that overflows int32")
155 }
156 e.Uint32(uint32(n))
157 }
158
159 func (e *encoder) IntAt(n int, at int) {
160 if n < 0 || int(int32(n)) != n {
161 base.Fatalf("go: attempting to write an int to the index that overflows int32")
162 }
163 binary.LittleEndian.PutUint32(e.b[at:], uint32(n))
164 }
165
View as plain text