...

Source file src/github.com/gogo/protobuf/proto/encode.go

Documentation: github.com/gogo/protobuf/proto

     1  // Go support for Protocol Buffers - Google's data interchange format
     2  //
     3  // Copyright 2010 The Go Authors.  All rights reserved.
     4  // https://github.com/golang/protobuf
     5  //
     6  // Redistribution and use in source and binary forms, with or without
     7  // modification, are permitted provided that the following conditions are
     8  // met:
     9  //
    10  //     * Redistributions of source code must retain the above copyright
    11  // notice, this list of conditions and the following disclaimer.
    12  //     * Redistributions in binary form must reproduce the above
    13  // copyright notice, this list of conditions and the following disclaimer
    14  // in the documentation and/or other materials provided with the
    15  // distribution.
    16  //     * Neither the name of Google Inc. nor the names of its
    17  // contributors may be used to endorse or promote products derived from
    18  // this software without specific prior written permission.
    19  //
    20  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    22  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    23  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31  
    32  package proto
    33  
    34  /*
    35   * Routines for encoding data into the wire format for protocol buffers.
    36   */
    37  
    38  import (
    39  	"errors"
    40  	"reflect"
    41  )
    42  
    43  var (
    44  	// errRepeatedHasNil is the error returned if Marshal is called with
    45  	// a struct with a repeated field containing a nil element.
    46  	errRepeatedHasNil = errors.New("proto: repeated field has nil element")
    47  
    48  	// errOneofHasNil is the error returned if Marshal is called with
    49  	// a struct with a oneof field containing a nil element.
    50  	errOneofHasNil = errors.New("proto: oneof field has nil value")
    51  
    52  	// ErrNil is the error returned if Marshal is called with nil.
    53  	ErrNil = errors.New("proto: Marshal called with nil")
    54  
    55  	// ErrTooLarge is the error returned if Marshal is called with a
    56  	// message that encodes to >2GB.
    57  	ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
    58  )
    59  
    60  // The fundamental encoders that put bytes on the wire.
    61  // Those that take integer types all accept uint64 and are
    62  // therefore of type valueEncoder.
    63  
    64  const maxVarintBytes = 10 // maximum length of a varint
    65  
    66  // EncodeVarint returns the varint encoding of x.
    67  // This is the format for the
    68  // int32, int64, uint32, uint64, bool, and enum
    69  // protocol buffer types.
    70  // Not used by the package itself, but helpful to clients
    71  // wishing to use the same encoding.
    72  func EncodeVarint(x uint64) []byte {
    73  	var buf [maxVarintBytes]byte
    74  	var n int
    75  	for n = 0; x > 127; n++ {
    76  		buf[n] = 0x80 | uint8(x&0x7F)
    77  		x >>= 7
    78  	}
    79  	buf[n] = uint8(x)
    80  	n++
    81  	return buf[0:n]
    82  }
    83  
    84  // EncodeVarint writes a varint-encoded integer to the Buffer.
    85  // This is the format for the
    86  // int32, int64, uint32, uint64, bool, and enum
    87  // protocol buffer types.
    88  func (p *Buffer) EncodeVarint(x uint64) error {
    89  	for x >= 1<<7 {
    90  		p.buf = append(p.buf, uint8(x&0x7f|0x80))
    91  		x >>= 7
    92  	}
    93  	p.buf = append(p.buf, uint8(x))
    94  	return nil
    95  }
    96  
    97  // SizeVarint returns the varint encoding size of an integer.
    98  func SizeVarint(x uint64) int {
    99  	switch {
   100  	case x < 1<<7:
   101  		return 1
   102  	case x < 1<<14:
   103  		return 2
   104  	case x < 1<<21:
   105  		return 3
   106  	case x < 1<<28:
   107  		return 4
   108  	case x < 1<<35:
   109  		return 5
   110  	case x < 1<<42:
   111  		return 6
   112  	case x < 1<<49:
   113  		return 7
   114  	case x < 1<<56:
   115  		return 8
   116  	case x < 1<<63:
   117  		return 9
   118  	}
   119  	return 10
   120  }
   121  
   122  // EncodeFixed64 writes a 64-bit integer to the Buffer.
   123  // This is the format for the
   124  // fixed64, sfixed64, and double protocol buffer types.
   125  func (p *Buffer) EncodeFixed64(x uint64) error {
   126  	p.buf = append(p.buf,
   127  		uint8(x),
   128  		uint8(x>>8),
   129  		uint8(x>>16),
   130  		uint8(x>>24),
   131  		uint8(x>>32),
   132  		uint8(x>>40),
   133  		uint8(x>>48),
   134  		uint8(x>>56))
   135  	return nil
   136  }
   137  
   138  // EncodeFixed32 writes a 32-bit integer to the Buffer.
   139  // This is the format for the
   140  // fixed32, sfixed32, and float protocol buffer types.
   141  func (p *Buffer) EncodeFixed32(x uint64) error {
   142  	p.buf = append(p.buf,
   143  		uint8(x),
   144  		uint8(x>>8),
   145  		uint8(x>>16),
   146  		uint8(x>>24))
   147  	return nil
   148  }
   149  
   150  // EncodeZigzag64 writes a zigzag-encoded 64-bit integer
   151  // to the Buffer.
   152  // This is the format used for the sint64 protocol buffer type.
   153  func (p *Buffer) EncodeZigzag64(x uint64) error {
   154  	// use signed number to get arithmetic right shift.
   155  	return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
   156  }
   157  
   158  // EncodeZigzag32 writes a zigzag-encoded 32-bit integer
   159  // to the Buffer.
   160  // This is the format used for the sint32 protocol buffer type.
   161  func (p *Buffer) EncodeZigzag32(x uint64) error {
   162  	// use signed number to get arithmetic right shift.
   163  	return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
   164  }
   165  
   166  // EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
   167  // This is the format used for the bytes protocol buffer
   168  // type and for embedded messages.
   169  func (p *Buffer) EncodeRawBytes(b []byte) error {
   170  	p.EncodeVarint(uint64(len(b)))
   171  	p.buf = append(p.buf, b...)
   172  	return nil
   173  }
   174  
   175  // EncodeStringBytes writes an encoded string to the Buffer.
   176  // This is the format used for the proto2 string type.
   177  func (p *Buffer) EncodeStringBytes(s string) error {
   178  	p.EncodeVarint(uint64(len(s)))
   179  	p.buf = append(p.buf, s...)
   180  	return nil
   181  }
   182  
   183  // Marshaler is the interface representing objects that can marshal themselves.
   184  type Marshaler interface {
   185  	Marshal() ([]byte, error)
   186  }
   187  
   188  // EncodeMessage writes the protocol buffer to the Buffer,
   189  // prefixed by a varint-encoded length.
   190  func (p *Buffer) EncodeMessage(pb Message) error {
   191  	siz := Size(pb)
   192  	sizVar := SizeVarint(uint64(siz))
   193  	p.grow(siz + sizVar)
   194  	p.EncodeVarint(uint64(siz))
   195  	return p.Marshal(pb)
   196  }
   197  
   198  // All protocol buffer fields are nillable, but be careful.
   199  func isNil(v reflect.Value) bool {
   200  	switch v.Kind() {
   201  	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
   202  		return v.IsNil()
   203  	}
   204  	return false
   205  }
   206  

View as plain text