fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

1package zoekt 2 3import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "unsafe" 8) 9 10// Wire-format of map[uint32]MinimalRepoListEntry is pretty straightforward: 11// 12// byte(2) version 13// uvarint(len(minimal)) 14// uvarint(sum(len(entry.Branches) for entry in minimal)) 15// for repoID, entry in minimal: 16// uvarint(repoID) 17// byte(entry.HasSymbols) 18// uvarint(entry.IndexTimeUnix) 19// uvarint(len(entry.Branches)) 20// for b in entry.Branches: 21// str(b.Name) 22// str(b.Version) 23// 24// Version 1 was the same, except it didn't have the IndexTimeUnix field. 25 26// reposMapEncode implements an efficient encoder for ReposMap. 27func reposMapEncode(minimal ReposMap) ([]byte, error) { 28 if minimal == nil { 29 return nil, nil 30 } 31 32 var b bytes.Buffer 33 var enc [binary.MaxVarintLen64]byte 34 varint := func(n int) { 35 m := binary.PutUvarint(enc[:], uint64(n)) 36 b.Write(enc[:m]) 37 } 38 str := func(s string) { 39 varint(len(s)) 40 b.WriteString(s) 41 } 42 strSize := func(s string) int { 43 return binary.PutUvarint(enc[:], uint64(len(s))) + len(s) 44 } 45 46 // We calculate this up front so when decoding we only need to allocate the 47 // underlying array once. 48 allBranchesLen := 0 49 for _, entry := range minimal { 50 allBranchesLen += len(entry.Branches) 51 } 52 53 // Calculate size 54 size := 1 // version 55 size += binary.PutUvarint(enc[:], uint64(len(minimal))) 56 size += binary.PutUvarint(enc[:], uint64(allBranchesLen)) 57 for repoID, entry := range minimal { 58 size += binary.PutUvarint(enc[:], uint64(repoID)) 59 size += 1 // HasSymbols 60 size += binary.PutUvarint(enc[:], uint64(entry.IndexTimeUnix)) 61 size += binary.PutUvarint(enc[:], uint64(len(entry.Branches))) 62 for _, b := range entry.Branches { 63 size += strSize(b.Name) 64 size += strSize(b.Version) 65 } 66 } 67 b.Grow(size) 68 69 // Version 70 b.WriteByte(2) 71 72 // Length 73 varint(len(minimal)) 74 75 varint(allBranchesLen) 76 77 for repoID, entry := range minimal { 78 varint(int(repoID)) 79 80 hasSymbols := byte(1) 81 if !entry.HasSymbols { 82 hasSymbols = 0 83 } 84 b.WriteByte(hasSymbols) 85 86 varint(int(entry.IndexTimeUnix)) 87 88 varint(len(entry.Branches)) 89 for _, b := range entry.Branches { 90 str(b.Name) 91 str(b.Version) 92 } 93 } 94 95 return b.Bytes(), nil 96} 97 98// reposMapDecode implements an efficient decoder for map[string]struct{}. 99func reposMapDecode(b []byte) (ReposMap, error) { 100 // nil input 101 if len(b) == 0 { 102 return nil, nil 103 } 104 105 // binaryReader returns strings pointing into b to avoid allocations. We 106 // don't own b, so we create a copy of it. 107 r := binaryReader{ 108 typ: "ReposMap", 109 b: append([]byte{}, b...), 110 } 111 112 // Version 113 var readIndexTime bool 114 v := r.byt() 115 switch v { 116 case 1: 117 readIndexTime = false 118 case 2: 119 readIndexTime = true 120 default: 121 return nil, fmt.Errorf("unsupported stringSet encoding version %d", v) 122 } 123 124 // Length 125 l := r.uvarint() 126 m := make(map[uint32]MinimalRepoListEntry, l) 127 128 // Pre-allocate slice for all branches 129 allBranchesLen := r.uvarint() 130 allBranches := make([]RepositoryBranch, 0, allBranchesLen) 131 132 for i := 0; i < l; i++ { 133 repoID := r.uvarint() 134 hasSymbols := r.byt() == 1 135 var indexTimeUnix int64 136 if readIndexTime { 137 indexTimeUnix = int64(r.uvarint()) 138 } 139 lb := r.uvarint() 140 for i := 0; i < lb; i++ { 141 allBranches = append(allBranches, RepositoryBranch{ 142 Name: r.str(), 143 Version: r.str(), 144 }) 145 } 146 branches := allBranches[len(allBranches)-lb:] 147 m[uint32(repoID)] = MinimalRepoListEntry{ 148 HasSymbols: hasSymbols, 149 Branches: branches, 150 IndexTimeUnix: indexTimeUnix, 151 } 152 } 153 154 return m, r.err 155} 156 157type binaryReader struct { 158 typ string 159 b []byte 160 err error 161} 162 163func (b *binaryReader) uvarint() int { 164 x, n := binary.Uvarint(b.b) 165 if n < 0 { 166 b.b = nil 167 b.err = fmt.Errorf("malformed %s", b.typ) 168 return 0 169 } 170 b.b = b.b[n:] 171 return int(x) 172} 173 174func (b *binaryReader) str() string { 175 l := b.uvarint() 176 if l > len(b.b) { 177 b.b = nil 178 b.err = fmt.Errorf("malformed %s", b.typ) 179 return "" 180 } 181 s := b2s(b.b[:l]) 182 b.b = b.b[l:] 183 return s 184} 185 186func (b *binaryReader) byt() byte { 187 if len(b.b) < 1 { 188 b.b = nil 189 b.err = fmt.Errorf("malformed %s", b.typ) 190 return 0 191 } 192 x := b.b[0] 193 b.b = b.b[1:] 194 return x 195} 196 197func b2s(b []byte) string { 198 return *(*string)(unsafe.Pointer(&b)) 199}