// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package pprof // A protobuf is a simple protocol buffer encoder. type protobuf struct { data []byte tmp [16]byte nest int } func (b *protobuf) varint(x uint64) { for x >= 128 { b.data = append(b.data, byte(x)|0x80) x >>= 7 } b.data = append(b.data, byte(x)) } func (b *protobuf) length(tag int, len int) { b.varint(uint64(tag)<<3 | 2) b.varint(uint64(len)) } func (b *protobuf) uint64(tag int, x uint64) { // append varint to b.data b.varint(uint64(tag)<<3 | 0) b.varint(x) } func (b *protobuf) uint64s(tag int, x []uint64) { if len(x) > 2 { // Use packed encoding n1 := len(b.data) for _, u := range x { b.varint(u) } n2 := len(b.data) b.length(tag, n2-n1) n3 := len(b.data) copy(b.tmp[:], b.data[n2:n3]) copy(b.data[n1+(n3-n2):], b.data[n1:n2]) copy(b.data[n1:], b.tmp[:n3-n2]) return } for _, u := range x { b.uint64(tag, u) } } func (b *protobuf) uint64Opt(tag int, x uint64) { if x == 0 { return } b.uint64(tag, x) } func (b *protobuf) int64(tag int, x int64) { u := uint64(x) b.uint64(tag, u) } func (b *protobuf) int64Opt(tag int, x int64) { if x == 0 { return } b.int64(tag, x) } func (b *protobuf) int64s(tag int, x []int64) { if len(x) > 2 { // Use packed encoding n1 := len(b.data) for _, u := range x { b.varint(uint64(u)) } n2 := len(b.data) b.length(tag, n2-n1) n3 := len(b.data) copy(b.tmp[:], b.data[n2:n3]) copy(b.data[n1+(n3-n2):], b.data[n1:n2]) copy(b.data[n1:], b.tmp[:n3-n2]) return } for _, u := range x { b.int64(tag, u) } } func (b *protobuf) string(tag int, x string) { b.length(tag, len(x)) b.data = append(b.data, x...) } func (b *protobuf) strings(tag int, x []string) { for _, s := range x { b.string(tag, s) } } func (b *protobuf) stringOpt(tag int, x string) { if x == "" { return } b.string(tag, x) } func (b *protobuf) bool(tag int, x bool) { if x { b.uint64(tag, 1) } else { b.uint64(tag, 0) } } func (b *protobuf) boolOpt(tag int, x bool) { if !x { return } b.bool(tag, x) } type msgOffset int func (b *protobuf) startMessage() msgOffset { b.nest++ return msgOffset(len(b.data)) } func (b *protobuf) endMessage(tag int, start msgOffset) { n1 := int(start) n2 := len(b.data) b.length(tag, n2-n1) n3 := len(b.data) copy(b.tmp[:], b.data[n2:n3]) copy(b.data[n1+(n3-n2):], b.data[n1:n2]) copy(b.data[n1:], b.tmp[:n3-n2]) b.nest-- }