github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/internal/profile/encode.go (about) 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 var err error 211 212 mappings := make(map[uint64]*Mapping) 213 for _, m := range p.Mapping { 214 m.File, err = getString(p.stringTable, &m.fileX, err) 215 m.BuildID, err = getString(p.stringTable, &m.buildIDX, err) 216 mappings[m.ID] = m 217 } 218 219 functions := make(map[uint64]*Function) 220 for _, f := range p.Function { 221 f.Name, err = getString(p.stringTable, &f.nameX, err) 222 f.SystemName, err = getString(p.stringTable, &f.systemNameX, err) 223 f.Filename, err = getString(p.stringTable, &f.filenameX, err) 224 functions[f.ID] = f 225 } 226 227 locations := make(map[uint64]*Location) 228 for _, l := range p.Location { 229 l.Mapping = mappings[l.mappingIDX] 230 l.mappingIDX = 0 231 for i, ln := range l.Line { 232 if id := ln.functionIDX; id != 0 { 233 l.Line[i].Function = functions[id] 234 if l.Line[i].Function == nil { 235 return fmt.Errorf("Function ID %d not found", id) 236 } 237 l.Line[i].functionIDX = 0 238 } 239 } 240 locations[l.ID] = l 241 } 242 243 for _, st := range p.SampleType { 244 st.Type, err = getString(p.stringTable, &st.typeX, err) 245 st.Unit, err = getString(p.stringTable, &st.unitX, err) 246 } 247 248 for _, s := range p.Sample { 249 labels := make(map[string][]string) 250 numLabels := make(map[string][]int64) 251 for _, l := range s.labelX { 252 var key, value string 253 key, err = getString(p.stringTable, &l.keyX, err) 254 if l.strX != 0 { 255 value, err = getString(p.stringTable, &l.strX, err) 256 labels[key] = append(labels[key], value) 257 } else { 258 numLabels[key] = append(numLabels[key], l.numX) 259 } 260 } 261 if len(labels) > 0 { 262 s.Label = labels 263 } 264 if len(numLabels) > 0 { 265 s.NumLabel = numLabels 266 } 267 s.Location = nil 268 for _, lid := range s.locationIDX { 269 s.Location = append(s.Location, locations[lid]) 270 } 271 s.locationIDX = nil 272 } 273 274 p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err) 275 p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err) 276 277 if pt := p.PeriodType; pt == nil { 278 p.PeriodType = &ValueType{} 279 } 280 281 if pt := p.PeriodType; pt != nil { 282 pt.Type, err = getString(p.stringTable, &pt.typeX, err) 283 pt.Unit, err = getString(p.stringTable, &pt.unitX, err) 284 } 285 for _, i := range p.commentX { 286 var c string 287 c, err = getString(p.stringTable, &i, err) 288 p.Comments = append(p.Comments, c) 289 } 290 291 p.commentX = nil 292 p.DefaultSampleType, err = getString(p.stringTable, &p.defaultSampleTypeX, err) 293 p.stringTable = nil 294 return nil 295 } 296 297 func (p *ValueType) decoder() []decoder { 298 return valueTypeDecoder 299 } 300 301 func (p *ValueType) encode(b *buffer) { 302 encodeInt64Opt(b, 1, p.typeX) 303 encodeInt64Opt(b, 2, p.unitX) 304 } 305 306 var valueTypeDecoder = []decoder{ 307 nil, // 0 308 // optional int64 type = 1 309 func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) }, 310 // optional int64 unit = 2 311 func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) }, 312 } 313 314 func (p *Sample) decoder() []decoder { 315 return sampleDecoder 316 } 317 318 func (p *Sample) encode(b *buffer) { 319 encodeUint64s(b, 1, p.locationIDX) 320 for _, x := range p.Value { 321 encodeInt64(b, 2, x) 322 } 323 for _, x := range p.labelX { 324 encodeMessage(b, 3, x) 325 } 326 } 327 328 var sampleDecoder = []decoder{ 329 nil, // 0 330 // repeated uint64 location = 1 331 func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) }, 332 // repeated int64 value = 2 333 func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) }, 334 // repeated Label label = 3 335 func(b *buffer, m message) error { 336 s := m.(*Sample) 337 n := len(s.labelX) 338 s.labelX = append(s.labelX, Label{}) 339 return decodeMessage(b, &s.labelX[n]) 340 }, 341 } 342 343 func (p Label) decoder() []decoder { 344 return labelDecoder 345 } 346 347 func (p Label) encode(b *buffer) { 348 encodeInt64Opt(b, 1, p.keyX) 349 encodeInt64Opt(b, 2, p.strX) 350 encodeInt64Opt(b, 3, p.numX) 351 } 352 353 var labelDecoder = []decoder{ 354 nil, // 0 355 // optional int64 key = 1 356 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) }, 357 // optional int64 str = 2 358 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) }, 359 // optional int64 num = 3 360 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) }, 361 } 362 363 func (p *Mapping) decoder() []decoder { 364 return mappingDecoder 365 } 366 367 func (p *Mapping) encode(b *buffer) { 368 encodeUint64Opt(b, 1, p.ID) 369 encodeUint64Opt(b, 2, p.Start) 370 encodeUint64Opt(b, 3, p.Limit) 371 encodeUint64Opt(b, 4, p.Offset) 372 encodeInt64Opt(b, 5, p.fileX) 373 encodeInt64Opt(b, 6, p.buildIDX) 374 encodeBoolOpt(b, 7, p.HasFunctions) 375 encodeBoolOpt(b, 8, p.HasFilenames) 376 encodeBoolOpt(b, 9, p.HasLineNumbers) 377 encodeBoolOpt(b, 10, p.HasInlineFrames) 378 } 379 380 var mappingDecoder = []decoder{ 381 nil, // 0 382 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) }, // optional uint64 id = 1 383 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) }, // optional uint64 memory_offset = 2 384 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) }, // optional uint64 memory_limit = 3 385 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) }, // optional uint64 file_offset = 4 386 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) }, // optional int64 filename = 5 387 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) }, // optional int64 build_id = 6 388 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) }, // optional bool has_functions = 7 389 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) }, // optional bool has_filenames = 8 390 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) }, // optional bool has_line_numbers = 9 391 func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10 392 } 393 394 func (p *Location) decoder() []decoder { 395 return locationDecoder 396 } 397 398 func (p *Location) encode(b *buffer) { 399 encodeUint64Opt(b, 1, p.ID) 400 encodeUint64Opt(b, 2, p.mappingIDX) 401 encodeUint64Opt(b, 3, p.Address) 402 for i := range p.Line { 403 encodeMessage(b, 4, &p.Line[i]) 404 } 405 } 406 407 var locationDecoder = []decoder{ 408 nil, // 0 409 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) }, // optional uint64 id = 1; 410 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2; 411 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) }, // optional uint64 address = 3; 412 func(b *buffer, m message) error { // repeated Line line = 4 413 pp := m.(*Location) 414 n := len(pp.Line) 415 pp.Line = append(pp.Line, Line{}) 416 return decodeMessage(b, &pp.Line[n]) 417 }, 418 } 419 420 func (p *Line) decoder() []decoder { 421 return lineDecoder 422 } 423 424 func (p *Line) encode(b *buffer) { 425 encodeUint64Opt(b, 1, p.functionIDX) 426 encodeInt64Opt(b, 2, p.Line) 427 } 428 429 var lineDecoder = []decoder{ 430 nil, // 0 431 // optional uint64 function_id = 1 432 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) }, 433 // optional int64 line = 2 434 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) }, 435 } 436 437 func (p *Function) decoder() []decoder { 438 return functionDecoder 439 } 440 441 func (p *Function) encode(b *buffer) { 442 encodeUint64Opt(b, 1, p.ID) 443 encodeInt64Opt(b, 2, p.nameX) 444 encodeInt64Opt(b, 3, p.systemNameX) 445 encodeInt64Opt(b, 4, p.filenameX) 446 encodeInt64Opt(b, 5, p.StartLine) 447 } 448 449 var functionDecoder = []decoder{ 450 nil, // 0 451 // optional uint64 id = 1 452 func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) }, 453 // optional int64 function_name = 2 454 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) }, 455 // optional int64 function_system_name = 3 456 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) }, 457 // repeated int64 filename = 4 458 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) }, 459 // optional int64 start_line = 5 460 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) }, 461 } 462 463 func addString(strings map[string]int, s string) int64 { 464 i, ok := strings[s] 465 if !ok { 466 i = len(strings) 467 strings[s] = i 468 } 469 return int64(i) 470 } 471 472 func getString(strings []string, strng *int64, err error) (string, error) { 473 if err != nil { 474 return "", err 475 } 476 s := int(*strng) 477 if s < 0 || s >= len(strings) { 478 return "", errMalformed 479 } 480 *strng = 0 481 return strings[s], nil 482 }