...

Source file src/go.opencensus.io/tag/map_codec.go

Documentation: go.opencensus.io/tag

     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  
    16  package tag
    17  
    18  import (
    19  	"encoding/binary"
    20  	"fmt"
    21  )
    22  
    23  // KeyType defines the types of keys allowed. Currently only keyTypeString is
    24  // supported.
    25  type keyType byte
    26  
    27  const (
    28  	keyTypeString keyType = iota
    29  	keyTypeInt64
    30  	keyTypeTrue
    31  	keyTypeFalse
    32  
    33  	tagsVersionID = byte(0)
    34  )
    35  
    36  type 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.
    43  func (eg *encoderGRPC) writeTagString(k, v string) {
    44  	eg.writeByte(byte(keyTypeString))
    45  	eg.writeStringWithVarintLen(k)
    46  	eg.writeStringWithVarintLen(v)
    47  }
    48  
    49  func (eg *encoderGRPC) writeTagUint64(k string, i uint64) {
    50  	eg.writeByte(byte(keyTypeInt64))
    51  	eg.writeStringWithVarintLen(k)
    52  	eg.writeUint64(i)
    53  }
    54  
    55  func (eg *encoderGRPC) writeTagTrue(k string) {
    56  	eg.writeByte(byte(keyTypeTrue))
    57  	eg.writeStringWithVarintLen(k)
    58  }
    59  
    60  func (eg *encoderGRPC) writeTagFalse(k string) {
    61  	eg.writeByte(byte(keyTypeFalse))
    62  	eg.writeStringWithVarintLen(k)
    63  }
    64  
    65  func (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  
    74  func (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  
    83  func (eg *encoderGRPC) writeByte(v byte) {
    84  	eg.growIfRequired(1)
    85  	eg.buf[eg.writeIdx] = v
    86  	eg.writeIdx++
    87  }
    88  
    89  func (eg *encoderGRPC) writeUint32(i uint32) {
    90  	eg.growIfRequired(4)
    91  	binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i)
    92  	eg.writeIdx += 4
    93  }
    94  
    95  func (eg *encoderGRPC) writeUint64(i uint64) {
    96  	eg.growIfRequired(8)
    97  	binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i)
    98  	eg.writeIdx += 8
    99  }
   100  
   101  func (eg *encoderGRPC) readByte() byte {
   102  	b := eg.buf[eg.readIdx]
   103  	eg.readIdx++
   104  	return b
   105  }
   106  
   107  func (eg *encoderGRPC) readUint32() uint32 {
   108  	i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:])
   109  	eg.readIdx += 4
   110  	return i
   111  }
   112  
   113  func (eg *encoderGRPC) readUint64() uint64 {
   114  	i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:])
   115  	eg.readIdx += 8
   116  	return i
   117  }
   118  
   119  func (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  
   138  func (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  
   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)
   149  		copy(tmp, eg.buf)
   150  		eg.buf = tmp
   151  	}
   152  }
   153  
   154  func (eg *encoderGRPC) readEnded() bool {
   155  	return eg.readIdx >= len(eg.buf)
   156  }
   157  
   158  func (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.
   164  func 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.
   183  func 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.
   195  func 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  

View as plain text