1 // Copyright 2017, OpenCensus Authors
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.
23 // KeyType defines the types of keys allowed. Currently only keyTypeString is
28 keyTypeString keyType = iota
33 tagsVersionID = byte(0)
36 type encoderGRPC struct {
41 // writeKeyString writes the fieldID '0' followed by the key string and value
43 func (eg *encoderGRPC) writeTagString(k, v string) {
44 eg.writeByte(byte(keyTypeString))
45 eg.writeStringWithVarintLen(k)
46 eg.writeStringWithVarintLen(v)
49 func (eg *encoderGRPC) writeTagUint64(k string, i uint64) {
50 eg.writeByte(byte(keyTypeInt64))
51 eg.writeStringWithVarintLen(k)
55 func (eg *encoderGRPC) writeTagTrue(k string) {
56 eg.writeByte(byte(keyTypeTrue))
57 eg.writeStringWithVarintLen(k)
60 func (eg *encoderGRPC) writeTagFalse(k string) {
61 eg.writeByte(byte(keyTypeFalse))
62 eg.writeStringWithVarintLen(k)
65 func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) {
68 eg.growIfRequired(binary.MaxVarintLen64 + length)
69 eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
70 copy(eg.buf[eg.writeIdx:], bytes)
74 func (eg *encoderGRPC) writeStringWithVarintLen(s string) {
77 eg.growIfRequired(binary.MaxVarintLen64 + length)
78 eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
79 copy(eg.buf[eg.writeIdx:], s)
83 func (eg *encoderGRPC) writeByte(v byte) {
85 eg.buf[eg.writeIdx] = v
89 func (eg *encoderGRPC) writeUint32(i uint32) {
91 binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i)
95 func (eg *encoderGRPC) writeUint64(i uint64) {
97 binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i)
101 func (eg *encoderGRPC) readByte() byte {
102 b := eg.buf[eg.readIdx]
107 func (eg *encoderGRPC) readUint32() uint32 {
108 i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:])
113 func (eg *encoderGRPC) readUint64() uint64 {
114 i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:])
119 func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) {
121 return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
123 length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:])
125 return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
128 valueStart += eg.readIdx
129 valueEnd := valueStart + int(length)
130 if valueEnd > len(eg.buf) {
131 return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf))
134 eg.readIdx = valueEnd
135 return eg.buf[valueStart:valueEnd], nil
138 func (eg *encoderGRPC) readStringWithVarintLen() (string, error) {
139 bytes, err := eg.readBytesWithVarintLen()
143 return string(bytes), nil
146 func (eg *encoderGRPC) growIfRequired(expected int) {
147 if len(eg.buf)-eg.writeIdx < expected {
148 tmp := make([]byte, 2*(len(eg.buf)+1)+expected)
154 func (eg *encoderGRPC) readEnded() bool {
155 return eg.readIdx >= len(eg.buf)
158 func (eg *encoderGRPC) bytes() []byte {
159 return eg.buf[:eg.writeIdx]
162 // Encode encodes the tag map into a []byte. It is useful to propagate
163 // the tag maps on wire in binary format.
164 func Encode(m *Map) []byte {
169 buf: make([]byte, len(m.m)),
171 eg.writeByte(byte(tagsVersionID))
172 for k, v := range m.m {
173 eg.writeByte(byte(keyTypeString))
174 eg.writeStringWithVarintLen(k.name)
175 eg.writeBytesWithVarintLen([]byte(v))
180 // Decode decodes the given []byte into a tag map.
181 func Decode(bytes []byte) (*Map, error) {
183 err := DecodeEach(bytes, ts.upsert)
185 // no partial failures
191 // DecodeEach decodes the given serialized tag map, calling handler for each
192 // tag key and value decoded.
193 func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
197 if len(eg.buf) == 0 {
201 version := eg.readByte()
202 if version > tagsVersionID {
203 return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID)
206 for !eg.readEnded() {
207 typ := keyType(eg.readByte())
209 if typ != keyTypeString {
210 return fmt.Errorf("cannot decode: invalid key type: %q", typ)
213 k, err := eg.readBytesWithVarintLen()
218 v, err := eg.readBytesWithVarintLen()
223 key, err := NewKey(string(k))
228 if !checkValue(val) {
229 return errInvalidValue