1 // Copyright 2022 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 const indexVersion = "go index v1" // 11 bytes (plus \n), to align uint32s in index
16 // encodeModuleBytes produces the encoded representation of the module index.
17 // encodeModuleBytes may modify the packages slice.
18 func encodeModuleBytes(packages []*rawPackage) []byte {
20 e.Bytes([]byte(indexVersion + "\n"))
21 stringTableOffsetPos := e.Pos() // fill this at the end
22 e.Uint32(0) // string table offset
23 sort.Slice(packages, func(i, j int) bool {
24 return packages[i].dir < packages[j].dir
27 packagesPos := e.Pos()
28 for _, p := range packages {
32 for i, p := range packages {
33 e.IntAt(e.Pos(), packagesPos+8*i+4)
36 e.IntAt(e.Pos(), stringTableOffsetPos)
37 e.Bytes(e.stringTable)
38 e.Bytes([]byte{0xFF}) // end of string table marker
42 func encodePackageBytes(p *rawPackage) []byte {
43 return encodeModuleBytes([]*rawPackage{p})
46 func encodePackage(e *encoder, p *rawPackage) {
49 e.Int(len(p.sourceFiles)) // number of source files
50 sourceFileOffsetPos := e.Pos() // the pos of the start of the source file offsets
51 for range p.sourceFiles {
54 for i, f := range p.sourceFiles {
55 e.IntAt(e.Pos(), sourceFileOffsetPos+4*i)
60 func encodeFile(e *encoder, f *rawFile) {
62 e.String(f.parseError)
68 e.String(f.cgoDirectives)
69 e.String(f.goBuildConstraint)
71 e.Int(len(f.plusBuildConstraints))
72 for _, s := range f.plusBuildConstraints {
77 for _, m := range f.imports {
79 e.Position(m.position)
83 for _, embed := range f.embeds {
84 e.String(embed.pattern)
85 e.Position(embed.position)
89 func newEncoder() *encoder {
90 e := &encoder{strings: make(map[string]int)}
92 // place the empty string at position 0 in the string table
93 e.stringTable = append(e.stringTable, 0)
99 func (e *encoder) Position(position token.Position) {
100 e.String(position.Filename)
101 e.Int(position.Offset)
103 e.Int(position.Column)
106 type encoder struct {
109 strings map[string]int
112 func (e *encoder) Pos() int {
116 func (e *encoder) Bytes(b []byte) {
117 e.b = append(e.b, b...)
120 func (e *encoder) String(s string) {
121 if n, ok := e.strings[s]; ok {
125 pos := len(e.stringTable)
128 e.stringTable = binary.AppendUvarint(e.stringTable, uint64(len(s)))
129 e.stringTable = append(e.stringTable, s...)
132 func (e *encoder) Bool(b bool) {
140 func (e *encoder) Uint32(n uint32) {
141 e.b = binary.LittleEndian.AppendUint32(e.b, n)
144 // Int encodes n. Note that all ints are written to the index as uint32s,
145 // and to avoid problems on 32-bit systems we require fitting into a 32-bit int.
146 func (e *encoder) Int(n int) {
147 if n < 0 || int(int32(n)) != n {
148 base.Fatalf("go: attempting to write an int to the index that overflows int32")
153 func (e *encoder) IntAt(n int, at int) {
154 if n < 0 || int(int32(n)) != n {
155 base.Fatalf("go: attempting to write an int to the index that overflows int32")
157 binary.LittleEndian.PutUint32(e.b[at:], uint32(n))