fork of https://github.com/sourcegraph/zoekt
1// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package index
16
17import (
18 "encoding/binary"
19 "io"
20 "log"
21)
22
23var _ = log.Println
24
25// writer is an io.Writer that keeps track of errors and offsets
26type writer struct {
27 err error
28 w io.Writer
29 off uint32
30}
31
32func (w *writer) Write(b []byte) (int, error) {
33 if w.err != nil {
34 return 0, w.err
35 }
36
37 var n int
38 n, w.err = w.w.Write(b)
39 w.off += uint32(n)
40 return n, w.err
41}
42
43func (w *writer) Off() uint32 { return w.off }
44
45func (w *writer) B(b byte) {
46 s := []byte{b}
47 w.Write(s)
48}
49
50func (w *writer) U32(n uint32) {
51 var enc [4]byte
52 binary.BigEndian.PutUint32(enc[:], n)
53 w.Write(enc[:])
54}
55
56func (w *writer) U64(n uint64) {
57 var enc [8]byte
58 binary.BigEndian.PutUint64(enc[:], n)
59 w.Write(enc[:])
60}
61
62func (w *writer) Varint(n uint32) {
63 var enc [8]byte
64 m := binary.PutUvarint(enc[:], uint64(n))
65 w.Write(enc[:m])
66}
67
68func (w *writer) String(s string) {
69 b := []byte(s)
70 w.Varint(uint32(len(b)))
71 w.Write(b)
72}
73
74func (s *simpleSection) start(w *writer) {
75 s.off = w.Off()
76}
77
78func (s *simpleSection) end(w *writer) {
79 s.sz = w.Off() - s.off
80}
81
82// section is a range of bytes in the index file.
83type section interface {
84 read(*reader) error
85 // skip advances over the data in the section without reading it.
86 // NOTE: the section will not contain valid data after this call, and it should not be used.
87 skip(*reader) error
88 write(*writer)
89 // kind encodes whether the section is simple or compound, and is used in serialization
90 kind() sectionKind
91}
92
93type sectionKind int
94
95const (
96 sectionKindSimple sectionKind = 0
97 sectionKindCompound sectionKind = 1
98 sectionKindCompoundLazy sectionKind = 2
99)
100
101// simpleSection is a simple range of bytes.
102type simpleSection struct {
103 off uint32
104 sz uint32
105}
106
107func (s *simpleSection) kind() sectionKind {
108 return sectionKindSimple
109}
110
111func (s *simpleSection) read(r *reader) error {
112 var err error
113 s.off, err = r.U32()
114 if err != nil {
115 return err
116 }
117 s.sz, err = r.U32()
118 return err
119}
120
121func (s *simpleSection) skip(r *reader) error {
122 var err error
123 _, err = r.U32()
124 if err != nil {
125 return err
126 }
127 _, err = r.U32()
128 return err
129}
130
131func (s *simpleSection) write(w *writer) {
132 w.U32(s.off)
133 w.U32(s.sz)
134}
135
136// compoundSection is a range of bytes containg a list of variable
137// sized items.
138type compoundSection struct {
139 data simpleSection
140
141 offsets []uint32
142 index simpleSection
143}
144
145func (s *compoundSection) kind() sectionKind {
146 return sectionKindCompound
147}
148
149func (s *compoundSection) start(w *writer) {
150 s.data.start(w)
151}
152
153func (s *compoundSection) end(w *writer) {
154 s.data.end(w)
155 s.index.start(w)
156 for _, o := range s.offsets {
157 w.U32(o)
158 }
159 s.index.end(w)
160}
161
162func (s *compoundSection) addItem(w *writer, item []byte) {
163 s.offsets = append(s.offsets, w.Off())
164 w.Write(item)
165}
166
167func (s *compoundSection) write(w *writer) {
168 s.data.write(w)
169 s.index.write(w)
170}
171
172func (s *compoundSection) read(r *reader) error {
173 if err := s.data.read(r); err != nil {
174 return err
175 }
176 if err := s.index.read(r); err != nil {
177 return err
178 }
179 var err error
180 s.offsets, err = readSectionU32(r.r, s.index)
181 return err
182}
183
184func (s *compoundSection) skip(r *reader) error {
185 if err := s.data.skip(r); err != nil {
186 return err
187 }
188 if err := s.index.read(r); err != nil {
189 return err
190 }
191
192 _, err := r.r.Read(s.index.off, s.index.sz)
193 return err
194}
195
196// relativeIndex returns the relative offsets of the items (first
197// element is 0), plus a final marking the end of the last item.
198func (s *compoundSection) relativeIndex() []uint32 {
199 ri := make([]uint32, 0, len(s.offsets)+1)
200 for _, o := range s.offsets {
201 ri = append(ri, o-s.offsets[0])
202 }
203 if len(s.offsets) > 0 {
204 ri = append(ri, s.data.sz)
205 }
206 return ri
207}
208
209type lazyCompoundSection struct {
210 compoundSection
211}
212
213func (s *lazyCompoundSection) kind() sectionKind {
214 return sectionKindCompoundLazy
215}
216
217func (s *lazyCompoundSection) read(r *reader) error {
218 // We do the same thing compoundSection.read does, except we don't read the
219 // offsets.
220 if err := s.data.read(r); err != nil {
221 return err
222 }
223 return s.index.read(r)
224}