1
// Copyright 2014 Google Inc. All Rights Reserved.
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
7
// http://www.apache.org/licenses/LICENSE-2.0
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.
22
func (p *Profile) decoder() []decoder {
26
// preEncode populates the unexported fields to be used by encode
27
// (with suffix X) from the corresponding exported fields. The
28
// exported fields are cleared up to facilitate testing.
29
func (p *Profile) preEncode() {
30
strings := make(map[string]int)
31
addString(strings, "")
33
for _, st := range p.SampleType {
34
st.typeX = addString(strings, st.Type)
35
st.unitX = addString(strings, st.Unit)
38
for _, s := range p.Sample {
41
for k := range s.Label {
42
keys = append(keys, k)
45
for _, k := range keys {
47
for _, v := range vs {
48
s.labelX = append(s.labelX,
50
keyX: addString(strings, k),
51
strX: addString(strings, v),
57
for k := range s.NumLabel {
58
numKeys = append(numKeys, k)
61
for _, k := range numKeys {
62
keyX := addString(strings, k)
65
for i, v := range vs {
68
unitX = addString(strings, units[i])
70
s.labelX = append(s.labelX,
79
s.locationIDX = make([]uint64, len(s.Location))
80
for i, loc := range s.Location {
81
s.locationIDX[i] = loc.ID
85
for _, m := range p.Mapping {
86
m.fileX = addString(strings, m.File)
87
m.buildIDX = addString(strings, m.BuildID)
90
for _, l := range p.Location {
91
for i, ln := range l.Line {
92
if ln.Function != nil {
93
l.Line[i].functionIDX = ln.Function.ID
95
l.Line[i].functionIDX = 0
99
l.mappingIDX = l.Mapping.ID
104
for _, f := range p.Function {
105
f.nameX = addString(strings, f.Name)
106
f.systemNameX = addString(strings, f.SystemName)
107
f.filenameX = addString(strings, f.Filename)
110
p.dropFramesX = addString(strings, p.DropFrames)
111
p.keepFramesX = addString(strings, p.KeepFrames)
113
if pt := p.PeriodType; pt != nil {
114
pt.typeX = addString(strings, pt.Type)
115
pt.unitX = addString(strings, pt.Unit)
119
for _, c := range p.Comments {
120
p.commentX = append(p.commentX, addString(strings, c))
123
p.defaultSampleTypeX = addString(strings, p.DefaultSampleType)
125
p.stringTable = make([]string, len(strings))
126
for s, i := range strings {
131
func (p *Profile) encode(b *buffer) {
132
for _, x := range p.SampleType {
133
encodeMessage(b, 1, x)
135
for _, x := range p.Sample {
136
encodeMessage(b, 2, x)
138
for _, x := range p.Mapping {
139
encodeMessage(b, 3, x)
141
for _, x := range p.Location {
142
encodeMessage(b, 4, x)
144
for _, x := range p.Function {
145
encodeMessage(b, 5, x)
147
encodeStrings(b, 6, p.stringTable)
148
encodeInt64Opt(b, 7, p.dropFramesX)
149
encodeInt64Opt(b, 8, p.keepFramesX)
150
encodeInt64Opt(b, 9, p.TimeNanos)
151
encodeInt64Opt(b, 10, p.DurationNanos)
152
if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
153
encodeMessage(b, 11, p.PeriodType)
155
encodeInt64Opt(b, 12, p.Period)
156
encodeInt64s(b, 13, p.commentX)
157
encodeInt64(b, 14, p.defaultSampleTypeX)
160
var profileDecoder = []decoder{
162
// repeated ValueType sample_type = 1
163
func(b *buffer, m message) error {
166
pp.SampleType = append(pp.SampleType, x)
167
return decodeMessage(b, x)
169
// repeated Sample sample = 2
170
func(b *buffer, m message) error {
173
pp.Sample = append(pp.Sample, x)
174
return decodeMessage(b, x)
176
// repeated Mapping mapping = 3
177
func(b *buffer, m message) error {
180
pp.Mapping = append(pp.Mapping, x)
181
return decodeMessage(b, x)
183
// repeated Location location = 4
184
func(b *buffer, m message) error {
186
x.Line = make([]Line, 0, 8) // Pre-allocate Line buffer
188
pp.Location = append(pp.Location, x)
189
err := decodeMessage(b, x)
191
x.Line = append(tmp, x.Line...) // Shrink to allocated size
194
// repeated Function function = 5
195
func(b *buffer, m message) error {
198
pp.Function = append(pp.Function, x)
199
return decodeMessage(b, x)
201
// repeated string string_table = 6
202
func(b *buffer, m message) error {
203
err := decodeStrings(b, &m.(*Profile).stringTable)
207
if m.(*Profile).stringTable[0] != "" {
208
return errors.New("string_table[0] must be ''")
212
// int64 drop_frames = 7
213
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
214
// int64 keep_frames = 8
215
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
216
// int64 time_nanos = 9
217
func(b *buffer, m message) error {
218
if m.(*Profile).TimeNanos != 0 {
219
return errConcatProfile
221
return decodeInt64(b, &m.(*Profile).TimeNanos)
223
// int64 duration_nanos = 10
224
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
225
// ValueType period_type = 11
226
func(b *buffer, m message) error {
230
return decodeMessage(b, x)
233
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
234
// repeated int64 comment = 13
235
func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Profile).commentX) },
236
// int64 defaultSampleType = 14
237
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).defaultSampleTypeX) },
240
// postDecode takes the unexported fields populated by decode (with
241
// suffix X) and populates the corresponding exported fields.
242
// The unexported fields are cleared up to facilitate testing.
243
func (p *Profile) postDecode() error {
245
mappings := make(map[uint64]*Mapping, len(p.Mapping))
246
mappingIds := make([]*Mapping, len(p.Mapping)+1)
247
for _, m := range p.Mapping {
248
m.File, err = getString(p.stringTable, &m.fileX, err)
249
m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
250
if m.ID < uint64(len(mappingIds)) {
257
functions := make(map[uint64]*Function, len(p.Function))
258
functionIds := make([]*Function, len(p.Function)+1)
259
for _, f := range p.Function {
260
f.Name, err = getString(p.stringTable, &f.nameX, err)
261
f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
262
f.Filename, err = getString(p.stringTable, &f.filenameX, err)
263
if f.ID < uint64(len(functionIds)) {
264
functionIds[f.ID] = f
270
locations := make(map[uint64]*Location, len(p.Location))
271
locationIds := make([]*Location, len(p.Location)+1)
272
for _, l := range p.Location {
273
if id := l.mappingIDX; id < uint64(len(mappingIds)) {
274
l.Mapping = mappingIds[id]
276
l.Mapping = mappings[id]
279
for i, ln := range l.Line {
280
if id := ln.functionIDX; id != 0 {
281
l.Line[i].functionIDX = 0
282
if id < uint64(len(functionIds)) {
283
l.Line[i].Function = functionIds[id]
285
l.Line[i].Function = functions[id]
289
if l.ID < uint64(len(locationIds)) {
290
locationIds[l.ID] = l
296
for _, st := range p.SampleType {
297
st.Type, err = getString(p.stringTable, &st.typeX, err)
298
st.Unit, err = getString(p.stringTable, &st.unitX, err)
301
for _, s := range p.Sample {
302
labels := make(map[string][]string, len(s.labelX))
303
numLabels := make(map[string][]int64, len(s.labelX))
304
numUnits := make(map[string][]string, len(s.labelX))
305
for _, l := range s.labelX {
306
var key, value string
307
key, err = getString(p.stringTable, &l.keyX, err)
309
value, err = getString(p.stringTable, &l.strX, err)
310
labels[key] = append(labels[key], value)
311
} else if l.numX != 0 || l.unitX != 0 {
312
numValues := numLabels[key]
313
units := numUnits[key]
316
unit, err = getString(p.stringTable, &l.unitX, err)
317
units = padStringArray(units, len(numValues))
318
numUnits[key] = append(units, unit)
320
numLabels[key] = append(numLabels[key], l.numX)
326
if len(numLabels) > 0 {
327
s.NumLabel = numLabels
328
for key, units := range numUnits {
330
numUnits[key] = padStringArray(units, len(numLabels[key]))
335
s.Location = make([]*Location, len(s.locationIDX))
336
for i, lid := range s.locationIDX {
337
if lid < uint64(len(locationIds)) {
338
s.Location[i] = locationIds[lid]
340
s.Location[i] = locations[lid]
346
p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
347
p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
349
if pt := p.PeriodType; pt == nil {
350
p.PeriodType = &ValueType{}
353
if pt := p.PeriodType; pt != nil {
354
pt.Type, err = getString(p.stringTable, &pt.typeX, err)
355
pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
358
for _, i := range p.commentX {
360
c, err = getString(p.stringTable, &i, err)
361
p.Comments = append(p.Comments, c)
365
p.DefaultSampleType, err = getString(p.stringTable, &p.defaultSampleTypeX, err)
370
// padStringArray pads arr with enough empty strings to make arr
371
// length l when arr's length is less than l.
372
func padStringArray(arr []string, l int) []string {
376
return append(arr, make([]string, l-len(arr))...)
379
func (p *ValueType) decoder() []decoder {
380
return valueTypeDecoder
383
func (p *ValueType) encode(b *buffer) {
384
encodeInt64Opt(b, 1, p.typeX)
385
encodeInt64Opt(b, 2, p.unitX)
388
var valueTypeDecoder = []decoder{
390
// optional int64 type = 1
391
func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
392
// optional int64 unit = 2
393
func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
396
func (p *Sample) decoder() []decoder {
400
func (p *Sample) encode(b *buffer) {
401
encodeUint64s(b, 1, p.locationIDX)
402
encodeInt64s(b, 2, p.Value)
403
for _, x := range p.labelX {
404
encodeMessage(b, 3, x)
408
var sampleDecoder = []decoder{
410
// repeated uint64 location = 1
411
func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
412
// repeated int64 value = 2
413
func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
414
// repeated Label label = 3
415
func(b *buffer, m message) error {
418
s.labelX = append(s.labelX, label{})
419
return decodeMessage(b, &s.labelX[n])
423
func (p label) decoder() []decoder {
427
func (p label) encode(b *buffer) {
428
encodeInt64Opt(b, 1, p.keyX)
429
encodeInt64Opt(b, 2, p.strX)
430
encodeInt64Opt(b, 3, p.numX)
431
encodeInt64Opt(b, 4, p.unitX)
434
var labelDecoder = []decoder{
436
// optional int64 key = 1
437
func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).keyX) },
438
// optional int64 str = 2
439
func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).strX) },
440
// optional int64 num = 3
441
func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).numX) },
442
// optional int64 num = 4
443
func(b *buffer, m message) error { return decodeInt64(b, &m.(*label).unitX) },
446
func (p *Mapping) decoder() []decoder {
447
return mappingDecoder
450
func (p *Mapping) encode(b *buffer) {
451
encodeUint64Opt(b, 1, p.ID)
452
encodeUint64Opt(b, 2, p.Start)
453
encodeUint64Opt(b, 3, p.Limit)
454
encodeUint64Opt(b, 4, p.Offset)
455
encodeInt64Opt(b, 5, p.fileX)
456
encodeInt64Opt(b, 6, p.buildIDX)
457
encodeBoolOpt(b, 7, p.HasFunctions)
458
encodeBoolOpt(b, 8, p.HasFilenames)
459
encodeBoolOpt(b, 9, p.HasLineNumbers)
460
encodeBoolOpt(b, 10, p.HasInlineFrames)
463
var mappingDecoder = []decoder{
465
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) }, // optional uint64 id = 1
466
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) }, // optional uint64 memory_offset = 2
467
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) }, // optional uint64 memory_limit = 3
468
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) }, // optional uint64 file_offset = 4
469
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) }, // optional int64 filename = 5
470
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) }, // optional int64 build_id = 6
471
func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) }, // optional bool has_functions = 7
472
func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) }, // optional bool has_filenames = 8
473
func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) }, // optional bool has_line_numbers = 9
474
func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
477
func (p *Location) decoder() []decoder {
478
return locationDecoder
481
func (p *Location) encode(b *buffer) {
482
encodeUint64Opt(b, 1, p.ID)
483
encodeUint64Opt(b, 2, p.mappingIDX)
484
encodeUint64Opt(b, 3, p.Address)
485
for i := range p.Line {
486
encodeMessage(b, 4, &p.Line[i])
488
encodeBoolOpt(b, 5, p.IsFolded)
491
var locationDecoder = []decoder{
493
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) }, // optional uint64 id = 1;
494
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
495
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) }, // optional uint64 address = 3;
496
func(b *buffer, m message) error { // repeated Line line = 4
499
pp.Line = append(pp.Line, Line{})
500
return decodeMessage(b, &pp.Line[n])
502
func(b *buffer, m message) error { return decodeBool(b, &m.(*Location).IsFolded) }, // optional bool is_folded = 5;
505
func (p *Line) decoder() []decoder {
509
func (p *Line) encode(b *buffer) {
510
encodeUint64Opt(b, 1, p.functionIDX)
511
encodeInt64Opt(b, 2, p.Line)
514
var lineDecoder = []decoder{
516
// optional uint64 function_id = 1
517
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
518
// optional int64 line = 2
519
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
522
func (p *Function) decoder() []decoder {
523
return functionDecoder
526
func (p *Function) encode(b *buffer) {
527
encodeUint64Opt(b, 1, p.ID)
528
encodeInt64Opt(b, 2, p.nameX)
529
encodeInt64Opt(b, 3, p.systemNameX)
530
encodeInt64Opt(b, 4, p.filenameX)
531
encodeInt64Opt(b, 5, p.StartLine)
534
var functionDecoder = []decoder{
536
// optional uint64 id = 1
537
func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
538
// optional int64 function_name = 2
539
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
540
// optional int64 function_system_name = 3
541
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
542
// repeated int64 filename = 4
543
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
544
// optional int64 start_line = 5
545
func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
548
func addString(strings map[string]int, s string) int64 {
557
func getString(strings []string, strng *int64, err error) (string, error) {
562
if s < 0 || s >= len(strings) {
563
return "", errMalformed
566
return strings[s], nil