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 if m == nil { 166 return nil 167 } 168 eg := &encoderGRPC{ 169 buf: make([]byte, len(m.m)), 170 } 171 eg.writeByte(tagsVersionID) 172 for k, v := range m.m { 173 if v.m.ttl.ttl == valueTTLUnlimitedPropagation { 174 eg.writeByte(byte(keyTypeString)) 175 eg.writeStringWithVarintLen(k.name) 176 eg.writeBytesWithVarintLen([]byte(v.value)) 177 } 178 } 179 return eg.bytes() 180} 181 182// Decode decodes the given []byte into a tag map. 183func Decode(bytes []byte) (*Map, error) { 184 ts := newMap() 185 err := DecodeEach(bytes, ts.upsert) 186 if err != nil { 187 // no partial failures 188 return nil, err 189 } 190 return ts, nil 191} 192 193// DecodeEach decodes the given serialized tag map, calling handler for each 194// tag key and value decoded. 195func DecodeEach(bytes []byte, fn func(key Key, val string, md metadatas)) error { 196 eg := &encoderGRPC{ 197 buf: bytes, 198 } 199 if len(eg.buf) == 0 { 200 return nil 201 } 202 203 version := eg.readByte() 204 if version > tagsVersionID { 205 return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID) 206 } 207 208 for !eg.readEnded() { 209 typ := keyType(eg.readByte()) 210 211 if typ != keyTypeString { 212 return fmt.Errorf("cannot decode: invalid key type: %q", typ) 213 } 214 215 k, err := eg.readBytesWithVarintLen() 216 if err != nil { 217 return err 218 } 219 220 v, err := eg.readBytesWithVarintLen() 221 if err != nil { 222 return err 223 } 224 225 key, err := NewKey(string(k)) 226 if err != nil { 227 return err 228 } 229 val := string(v) 230 if !checkValue(val) { 231 return errInvalidValue 232 } 233 fn(key, val, createMetadatas(WithTTL(TTLUnlimitedPropagation))) 234 if err != nil { 235 return err 236 } 237 } 238 return nil 239} 240