]> Cypherpunks.ru repositories - gostls13.git/blob - src/internal/profile/encode.go
internal/profile: actually return errors in postDecode
[gostls13.git] / src / internal / profile / encode.go
1 // Copyright 2014 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.
4
5 package profile
6
7 import (
8         "errors"
9         "fmt"
10         "sort"
11 )
12
13 func (p *Profile) decoder() []decoder {
14         return profileDecoder
15 }
16
17 // preEncode populates the unexported fields to be used by encode
18 // (with suffix X) from the corresponding exported fields. The
19 // exported fields are cleared up to facilitate testing.
20 func (p *Profile) preEncode() {
21         strings := make(map[string]int)
22         addString(strings, "")
23
24         for _, st := range p.SampleType {
25                 st.typeX = addString(strings, st.Type)
26                 st.unitX = addString(strings, st.Unit)
27         }
28
29         for _, s := range p.Sample {
30                 s.labelX = nil
31                 var keys []string
32                 for k := range s.Label {
33                         keys = append(keys, k)
34                 }
35                 sort.Strings(keys)
36                 for _, k := range keys {
37                         vs := s.Label[k]
38                         for _, v := range vs {
39                                 s.labelX = append(s.labelX,
40                                         Label{
41                                                 keyX: addString(strings, k),
42                                                 strX: addString(strings, v),
43                                         },
44                                 )
45                         }
46                 }
47                 var numKeys []string
48                 for k := range s.NumLabel {
49                         numKeys = append(numKeys, k)
50                 }
51                 sort.Strings(numKeys)
52                 for _, k := range numKeys {
53                         vs := s.NumLabel[k]
54                         for _, v := range vs {
55                                 s.labelX = append(s.labelX,
56                                         Label{
57                                                 keyX: addString(strings, k),
58                                                 numX: v,
59                                         },
60                                 )
61                         }
62                 }
63                 s.locationIDX = nil
64                 for _, l := range s.Location {
65                         s.locationIDX = append(s.locationIDX, l.ID)
66                 }
67         }
68
69         for _, m := range p.Mapping {
70                 m.fileX = addString(strings, m.File)
71                 m.buildIDX = addString(strings, m.BuildID)
72         }
73
74         for _, l := range p.Location {
75                 for i, ln := range l.Line {
76                         if ln.Function != nil {
77                                 l.Line[i].functionIDX = ln.Function.ID
78                         } else {
79                                 l.Line[i].functionIDX = 0
80                         }
81                 }
82                 if l.Mapping != nil {
83                         l.mappingIDX = l.Mapping.ID
84                 } else {
85                         l.mappingIDX = 0
86                 }
87         }
88         for _, f := range p.Function {
89                 f.nameX = addString(strings, f.Name)
90                 f.systemNameX = addString(strings, f.SystemName)
91                 f.filenameX = addString(strings, f.Filename)
92         }
93
94         p.dropFramesX = addString(strings, p.DropFrames)
95         p.keepFramesX = addString(strings, p.KeepFrames)
96
97         if pt := p.PeriodType; pt != nil {
98                 pt.typeX = addString(strings, pt.Type)
99                 pt.unitX = addString(strings, pt.Unit)
100         }
101
102         p.stringTable = make([]string, len(strings))
103         for s, i := range strings {
104                 p.stringTable[i] = s
105         }
106 }
107
108 func (p *Profile) encode(b *buffer) {
109         for _, x := range p.SampleType {
110                 encodeMessage(b, 1, x)
111         }
112         for _, x := range p.Sample {
113                 encodeMessage(b, 2, x)
114         }
115         for _, x := range p.Mapping {
116                 encodeMessage(b, 3, x)
117         }
118         for _, x := range p.Location {
119                 encodeMessage(b, 4, x)
120         }
121         for _, x := range p.Function {
122                 encodeMessage(b, 5, x)
123         }
124         encodeStrings(b, 6, p.stringTable)
125         encodeInt64Opt(b, 7, p.dropFramesX)
126         encodeInt64Opt(b, 8, p.keepFramesX)
127         encodeInt64Opt(b, 9, p.TimeNanos)
128         encodeInt64Opt(b, 10, p.DurationNanos)
129         if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
130                 encodeMessage(b, 11, p.PeriodType)
131         }
132         encodeInt64Opt(b, 12, p.Period)
133 }
134
135 var profileDecoder = []decoder{
136         nil, // 0
137         // repeated ValueType sample_type = 1
138         func(b *buffer, m message) error {
139                 x := new(ValueType)
140                 pp := m.(*Profile)
141                 pp.SampleType = append(pp.SampleType, x)
142                 return decodeMessage(b, x)
143         },
144         // repeated Sample sample = 2
145         func(b *buffer, m message) error {
146                 x := new(Sample)
147                 pp := m.(*Profile)
148                 pp.Sample = append(pp.Sample, x)
149                 return decodeMessage(b, x)
150         },
151         // repeated Mapping mapping = 3
152         func(b *buffer, m message) error {
153                 x := new(Mapping)
154                 pp := m.(*Profile)
155                 pp.Mapping = append(pp.Mapping, x)
156                 return decodeMessage(b, x)
157         },
158         // repeated Location location = 4
159         func(b *buffer, m message) error {
160                 x := new(Location)
161                 pp := m.(*Profile)
162                 pp.Location = append(pp.Location, x)
163                 return decodeMessage(b, x)
164         },
165         // repeated Function function = 5
166         func(b *buffer, m message) error {
167                 x := new(Function)
168                 pp := m.(*Profile)
169                 pp.Function = append(pp.Function, x)
170                 return decodeMessage(b, x)
171         },
172         // repeated string string_table = 6
173         func(b *buffer, m message) error {
174                 err := decodeStrings(b, &m.(*Profile).stringTable)
175                 if err != nil {
176                         return err
177                 }
178                 if m.(*Profile).stringTable[0] != "" {
179                         return errors.New("string_table[0] must be ''")
180                 }
181                 return nil
182         },
183         // repeated int64 drop_frames = 7
184         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
185         // repeated int64 keep_frames = 8
186         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
187         // repeated int64 time_nanos = 9
188         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).TimeNanos) },
189         // repeated int64 duration_nanos = 10
190         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
191         // optional string period_type = 11
192         func(b *buffer, m message) error {
193                 x := new(ValueType)
194                 pp := m.(*Profile)
195                 pp.PeriodType = x
196                 return decodeMessage(b, x)
197         },
198         // repeated int64 period = 12
199         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
200         // repeated int64 comment = 13
201         func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Profile).commentX) },
202         // int64 defaultSampleType = 14
203         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).defaultSampleTypeX) },
204 }
205
206 // postDecode takes the unexported fields populated by decode (with
207 // suffix X) and populates the corresponding exported fields.
208 // The unexported fields are cleared up to facilitate testing.
209 func (p *Profile) postDecode() error {
210         if p.Empty() {
211                 return nil
212         }
213         var err error
214
215         mappings := make(map[uint64]*Mapping)
216         for _, m := range p.Mapping {
217                 m.File, err = getString(p.stringTable, &m.fileX, err)
218                 m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
219                 mappings[m.ID] = m
220         }
221
222         functions := make(map[uint64]*Function)
223         for _, f := range p.Function {
224                 f.Name, err = getString(p.stringTable, &f.nameX, err)
225                 f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
226                 f.Filename, err = getString(p.stringTable, &f.filenameX, err)
227                 functions[f.ID] = f
228         }
229
230         locations := make(map[uint64]*Location)
231         for _, l := range p.Location {
232                 l.Mapping = mappings[l.mappingIDX]
233                 l.mappingIDX = 0
234                 for i, ln := range l.Line {
235                         if id := ln.functionIDX; id != 0 {
236                                 l.Line[i].Function = functions[id]
237                                 if l.Line[i].Function == nil {
238                                         return fmt.Errorf("Function ID %d not found", id)
239                                 }
240                                 l.Line[i].functionIDX = 0
241                         }
242                 }
243                 locations[l.ID] = l
244         }
245
246         for _, st := range p.SampleType {
247                 st.Type, err = getString(p.stringTable, &st.typeX, err)
248                 st.Unit, err = getString(p.stringTable, &st.unitX, err)
249         }
250
251         for _, s := range p.Sample {
252                 labels := make(map[string][]string)
253                 numLabels := make(map[string][]int64)
254                 for _, l := range s.labelX {
255                         var key, value string
256                         key, err = getString(p.stringTable, &l.keyX, err)
257                         if l.strX != 0 {
258                                 value, err = getString(p.stringTable, &l.strX, err)
259                                 labels[key] = append(labels[key], value)
260                         } else {
261                                 numLabels[key] = append(numLabels[key], l.numX)
262                         }
263                 }
264                 if len(labels) > 0 {
265                         s.Label = labels
266                 }
267                 if len(numLabels) > 0 {
268                         s.NumLabel = numLabels
269                 }
270                 s.Location = nil
271                 for _, lid := range s.locationIDX {
272                         s.Location = append(s.Location, locations[lid])
273                 }
274                 s.locationIDX = nil
275         }
276
277         p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
278         p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
279
280         if pt := p.PeriodType; pt == nil {
281                 p.PeriodType = &ValueType{}
282         }
283
284         if pt := p.PeriodType; pt != nil {
285                 pt.Type, err = getString(p.stringTable, &pt.typeX, err)
286                 pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
287         }
288         for _, i := range p.commentX {
289                 var c string
290                 c, err = getString(p.stringTable, &i, err)
291                 p.Comments = append(p.Comments, c)
292         }
293
294         p.commentX = nil
295         p.DefaultSampleType, err = getString(p.stringTable, &p.defaultSampleTypeX, err)
296         p.stringTable = nil
297         return err
298 }
299
300 func (p *ValueType) decoder() []decoder {
301         return valueTypeDecoder
302 }
303
304 func (p *ValueType) encode(b *buffer) {
305         encodeInt64Opt(b, 1, p.typeX)
306         encodeInt64Opt(b, 2, p.unitX)
307 }
308
309 var valueTypeDecoder = []decoder{
310         nil, // 0
311         // optional int64 type = 1
312         func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
313         // optional int64 unit = 2
314         func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
315 }
316
317 func (p *Sample) decoder() []decoder {
318         return sampleDecoder
319 }
320
321 func (p *Sample) encode(b *buffer) {
322         encodeUint64s(b, 1, p.locationIDX)
323         for _, x := range p.Value {
324                 encodeInt64(b, 2, x)
325         }
326         for _, x := range p.labelX {
327                 encodeMessage(b, 3, x)
328         }
329 }
330
331 var sampleDecoder = []decoder{
332         nil, // 0
333         // repeated uint64 location = 1
334         func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
335         // repeated int64 value = 2
336         func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
337         // repeated Label label = 3
338         func(b *buffer, m message) error {
339                 s := m.(*Sample)
340                 n := len(s.labelX)
341                 s.labelX = append(s.labelX, Label{})
342                 return decodeMessage(b, &s.labelX[n])
343         },
344 }
345
346 func (p Label) decoder() []decoder {
347         return labelDecoder
348 }
349
350 func (p Label) encode(b *buffer) {
351         encodeInt64Opt(b, 1, p.keyX)
352         encodeInt64Opt(b, 2, p.strX)
353         encodeInt64Opt(b, 3, p.numX)
354 }
355
356 var labelDecoder = []decoder{
357         nil, // 0
358         // optional int64 key = 1
359         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) },
360         // optional int64 str = 2
361         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) },
362         // optional int64 num = 3
363         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) },
364 }
365
366 func (p *Mapping) decoder() []decoder {
367         return mappingDecoder
368 }
369
370 func (p *Mapping) encode(b *buffer) {
371         encodeUint64Opt(b, 1, p.ID)
372         encodeUint64Opt(b, 2, p.Start)
373         encodeUint64Opt(b, 3, p.Limit)
374         encodeUint64Opt(b, 4, p.Offset)
375         encodeInt64Opt(b, 5, p.fileX)
376         encodeInt64Opt(b, 6, p.buildIDX)
377         encodeBoolOpt(b, 7, p.HasFunctions)
378         encodeBoolOpt(b, 8, p.HasFilenames)
379         encodeBoolOpt(b, 9, p.HasLineNumbers)
380         encodeBoolOpt(b, 10, p.HasInlineFrames)
381 }
382
383 var mappingDecoder = []decoder{
384         nil, // 0
385         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) },            // optional uint64 id = 1
386         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) },         // optional uint64 memory_offset = 2
387         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) },         // optional uint64 memory_limit = 3
388         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) },        // optional uint64 file_offset = 4
389         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) },          // optional int64 filename = 5
390         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) },       // optional int64 build_id = 6
391         func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) },    // optional bool has_functions = 7
392         func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) },    // optional bool has_filenames = 8
393         func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) },  // optional bool has_line_numbers = 9
394         func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
395 }
396
397 func (p *Location) decoder() []decoder {
398         return locationDecoder
399 }
400
401 func (p *Location) encode(b *buffer) {
402         encodeUint64Opt(b, 1, p.ID)
403         encodeUint64Opt(b, 2, p.mappingIDX)
404         encodeUint64Opt(b, 3, p.Address)
405         for i := range p.Line {
406                 encodeMessage(b, 4, &p.Line[i])
407         }
408 }
409
410 var locationDecoder = []decoder{
411         nil, // 0
412         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) },         // optional uint64 id = 1;
413         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
414         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) },    // optional uint64 address = 3;
415         func(b *buffer, m message) error { // repeated Line line = 4
416                 pp := m.(*Location)
417                 n := len(pp.Line)
418                 pp.Line = append(pp.Line, Line{})
419                 return decodeMessage(b, &pp.Line[n])
420         },
421 }
422
423 func (p *Line) decoder() []decoder {
424         return lineDecoder
425 }
426
427 func (p *Line) encode(b *buffer) {
428         encodeUint64Opt(b, 1, p.functionIDX)
429         encodeInt64Opt(b, 2, p.Line)
430 }
431
432 var lineDecoder = []decoder{
433         nil, // 0
434         // optional uint64 function_id = 1
435         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
436         // optional int64 line = 2
437         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
438 }
439
440 func (p *Function) decoder() []decoder {
441         return functionDecoder
442 }
443
444 func (p *Function) encode(b *buffer) {
445         encodeUint64Opt(b, 1, p.ID)
446         encodeInt64Opt(b, 2, p.nameX)
447         encodeInt64Opt(b, 3, p.systemNameX)
448         encodeInt64Opt(b, 4, p.filenameX)
449         encodeInt64Opt(b, 5, p.StartLine)
450 }
451
452 var functionDecoder = []decoder{
453         nil, // 0
454         // optional uint64 id = 1
455         func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
456         // optional int64 function_name = 2
457         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
458         // optional int64 function_system_name = 3
459         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
460         // repeated int64 filename = 4
461         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
462         // optional int64 start_line = 5
463         func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
464 }
465
466 func addString(strings map[string]int, s string) int64 {
467         i, ok := strings[s]
468         if !ok {
469                 i = len(strings)
470                 strings[s] = i
471         }
472         return int64(i)
473 }
474
475 func getString(strings []string, strng *int64, err error) (string, error) {
476         if err != nil {
477                 return "", err
478         }
479         s := int(*strng)
480         if s < 0 || s >= len(strings) {
481                 return "", errMalformed
482         }
483         *strng = 0
484         return strings[s], nil
485 }