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 v2" // 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)
88 e.Int(len(f.directives))
89 for _, d := range f.directives {
95 func newEncoder() *encoder {
96 e := &encoder{strings: make(map[string]int)}
98 // place the empty string at position 0 in the string table
99 e.stringTable = append(e.stringTable, 0)
105 func (e *encoder) Position(position token.Position) {
106 e.String(position.Filename)
107 e.Int(position.Offset)
109 e.Int(position.Column)
112 type encoder struct {
115 strings map[string]int
118 func (e *encoder) Pos() int {
122 func (e *encoder) Bytes(b []byte) {
123 e.b = append(e.b, b...)
126 func (e *encoder) String(s string) {
127 if n, ok := e.strings[s]; ok {
131 pos := len(e.stringTable)
134 e.stringTable = binary.AppendUvarint(e.stringTable, uint64(len(s)))
135 e.stringTable = append(e.stringTable, s...)
138 func (e *encoder) Bool(b bool) {
146 func (e *encoder) Uint32(n uint32) {
147 e.b = binary.LittleEndian.AppendUint32(e.b, n)
150 // Int encodes n. Note that all ints are written to the index as uint32s,
151 // and to avoid problems on 32-bit systems we require fitting into a 32-bit int.
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")
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")
163 binary.LittleEndian.PutUint32(e.b[at:], uint32(n))