1// Copyright 2017, OpenCensus Authors 2// 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 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 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. 14// 15 16package tag 17 18import ( 19 "encoding/binary" 20 "fmt" 21) 22 23// KeyType defines the types of keys allowed. Currently only keyTypeString is 24// supported. 25type keyType byte 26 27const ( 28 keyTypeString keyType = iota 29 keyTypeInt64 30 keyTypeTrue 31 keyTypeFalse 32 33 tagsVersionID = byte(0) 34) 35 36type encoderGRPC struct { 37 buf []byte 38 writeIdx, readIdx int 39} 40 41// writeKeyString writes the fieldID '0' followed by the key string and value 42// string. 43func (eg *encoderGRPC) writeTagString(k, v string) { 44 eg.writeByte(byte(keyTypeString)) 45 eg.writeStringWithVarintLen(k) 46 eg.writeStringWithVarintLen(v) 47} 48 49func (eg *encoderGRPC) writeTagUint64(k string, i uint64) { 50 eg.writeByte(byte(keyTypeInt64)) 51 eg.writeStringWithVarintLen(k) 52 eg.writeUint64(i) 53} 54 55func (eg *encoderGRPC) writeTagTrue(k string) { 56 eg.writeByte(byte(keyTypeTrue)) 57 eg.writeStringWithVarintLen(k) 58} 59 60func (eg *encoderGRPC) writeTagFalse(k string) { 61 eg.writeByte(byte(keyTypeFalse)) 62 eg.writeStringWithVarintLen(k) 63} 64 65func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) { 66 length := len(bytes) 67 68 eg.growIfRequired(binary.MaxVarintLen64 + length) 69 eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) 70 copy(eg.buf[eg.writeIdx:], bytes) 71 eg.writeIdx += length 72} 73 74func (eg *encoderGRPC) writeStringWithVarintLen(s string) { 75 length := len(s) 76 77 eg.growIfRequired(binary.MaxVarintLen64 + length) 78 eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length)) 79 copy(eg.buf[eg.writeIdx:], s) 80 eg.writeIdx += length 81} 82 83func (eg *encoderGRPC) writeByte(v byte) { 84 eg.growIfRequired(1) 85 eg.buf[eg.writeIdx] = v 86 eg.writeIdx++ 87} 88 89func (eg *encoderGRPC) writeUint32(i uint32) { 90 eg.growIfRequired(4) 91 binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i) 92 eg.writeIdx += 4 93} 94 95func (eg *encoderGRPC) writeUint64(i uint64) { 96 eg.growIfRequired(8) 97 binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i) 98 eg.writeIdx += 8 99} 100 101func (eg *encoderGRPC) readByte() byte { 102 b := eg.buf[eg.readIdx] 103 eg.readIdx++ 104 return b 105} 106 107func (eg *encoderGRPC) readUint32() uint32 { 108 i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:]) 109 eg.readIdx += 4 110 return i 111} 112 113func (eg *encoderGRPC) readUint64() uint64 { 114 i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:]) 115 eg.readIdx += 8 116 return i 117} 118 119func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) { 120 if eg.readEnded() { 121 return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) 122 } 123 length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:]) 124 if valueStart <= 0 { 125 return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx) 126 } 127 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)) 132 } 133 134 eg.readIdx = valueEnd 135 return eg.buf[valueStart:valueEnd], nil 136} 137 138func (eg *encoderGRPC) readStringWithVarintLen() (string, error) { 139 bytes, err := eg.readBytesWithVarintLen() 140 if err != nil { 141 return "", err 142 } 143 return string(bytes), nil 144} 145 146func (eg *encoderGRPC) growIfRequired(expected int) { 147 if len(eg.buf)-eg.writeIdx < expected { 148 tmp := make([]byte, 2*(len(eg.buf)+1)+expected) 149 copy(tmp, eg.buf) 150 eg.buf = tmp 151 } 152} 153 154func (eg *encoderGRPC) readEnded() bool { 155 return eg.readIdx >= len(eg.buf) 156} 157 158func (eg *encoderGRPC) bytes() []byte { 159 return eg.buf[:eg.writeIdx] 160} 161 162// Encode encodes the tag map into a []byte. It is useful to propagate 163// the tag maps on wire in binary format. 164func Encode(m *Map) []byte { 165 eg := &encoderGRPC{ 166 buf: make([]byte, len(m.m)), 167 } 168 eg.writeByte(byte(tagsVersionID)) 169 for k, v := range m.m { 170 eg.writeByte(byte(keyTypeString)) 171 eg.writeStringWithVarintLen(k.name) 172 eg.writeBytesWithVarintLen([]byte(v)) 173 } 174 return eg.bytes() 175} 176 177// Decode decodes the given []byte into a tag map. 178func Decode(bytes []byte) (*Map, error) { 179 ts := newMap() 180 181 eg := &encoderGRPC{ 182 buf: bytes, 183 } 184 if len(eg.buf) == 0 { 185 return ts, nil 186 } 187 188 version := eg.readByte() 189 if version > tagsVersionID { 190 return nil, fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID) 191 } 192 193 for !eg.readEnded() { 194 typ := keyType(eg.readByte()) 195 196 if typ != keyTypeString { 197 return nil, fmt.Errorf("cannot decode: invalid key type: %q", typ) 198 } 199 200 k, err := eg.readBytesWithVarintLen() 201 if err != nil { 202 return nil, err 203 } 204 205 v, err := eg.readBytesWithVarintLen() 206 if err != nil { 207 return nil, err 208 } 209 210 key, err := NewKey(string(k)) 211 if err != nil { 212 return nil, err // no partial failures 213 } 214 val := string(v) 215 if !checkValue(val) { 216 return nil, errInvalidValue // no partial failures 217 } 218 ts.upsert(key, val) 219 } 220 return ts, nil 221} 222