| // Go support for Protocol Buffers - Google's data interchange format | |
| // | |
| // Copyright 2010 The Go Authors. All rights reserved. | |
| // https://github.com/golang/protobuf | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are | |
| // met: | |
| // | |
| // * Redistributions of source code must retain the above copyright | |
| // notice, this list of conditions and the following disclaimer. | |
| // * Redistributions in binary form must reproduce the above | |
| // copyright notice, this list of conditions and the following disclaimer | |
| // in the documentation and/or other materials provided with the | |
| // distribution. | |
| // * Neither the name of Google Inc. nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| package proto | |
| /* | |
| * Routines for encoding data into the wire format for protocol buffers. | |
| */ | |
| import ( | |
| "errors" | |
| "reflect" | |
| ) | |
| var ( | |
| // errRepeatedHasNil is the error returned if Marshal is called with | |
| // a struct with a repeated field containing a nil element. | |
| errRepeatedHasNil = errors.New("proto: repeated field has nil element") | |
| // errOneofHasNil is the error returned if Marshal is called with | |
| // a struct with a oneof field containing a nil element. | |
| errOneofHasNil = errors.New("proto: oneof field has nil value") | |
| // ErrNil is the error returned if Marshal is called with nil. | |
| ErrNil = errors.New("proto: Marshal called with nil") | |
| // ErrTooLarge is the error returned if Marshal is called with a | |
| // message that encodes to >2GB. | |
| ErrTooLarge = errors.New("proto: message encodes to over 2 GB") | |
| ) | |
| // The fundamental encoders that put bytes on the wire. | |
| // Those that take integer types all accept uint64 and are | |
| // therefore of type valueEncoder. | |
| const maxVarintBytes = 10 // maximum length of a varint | |
| // EncodeVarint returns the varint encoding of x. | |
| // This is the format for the | |
| // int32, int64, uint32, uint64, bool, and enum | |
| // protocol buffer types. | |
| // Not used by the package itself, but helpful to clients | |
| // wishing to use the same encoding. | |
| func EncodeVarint(x uint64) []byte { | |
| var buf [maxVarintBytes]byte | |
| var n int | |
| for n = 0; x > 127; n++ { | |
| buf[n] = 0x80 | uint8(x&0x7F) | |
| x >>= 7 | |
| } | |
| buf[n] = uint8(x) | |
| n++ | |
| return buf[0:n] | |
| } | |
| // EncodeVarint writes a varint-encoded integer to the Buffer. | |
| // This is the format for the | |
| // int32, int64, uint32, uint64, bool, and enum | |
| // protocol buffer types. | |
| func (p *Buffer) EncodeVarint(x uint64) error { | |
| for x >= 1<<7 { | |
| p.buf = append(p.buf, uint8(x&0x7f|0x80)) | |
| x >>= 7 | |
| } | |
| p.buf = append(p.buf, uint8(x)) | |
| return nil | |
| } | |
| // SizeVarint returns the varint encoding size of an integer. | |
| func SizeVarint(x uint64) int { | |
| switch { | |
| case x < 1<<7: | |
| return 1 | |
| case x < 1<<14: | |
| return 2 | |
| case x < 1<<21: | |
| return 3 | |
| case x < 1<<28: | |
| return 4 | |
| case x < 1<<35: | |
| return 5 | |
| case x < 1<<42: | |
| return 6 | |
| case x < 1<<49: | |
| return 7 | |
| case x < 1<<56: | |
| return 8 | |
| case x < 1<<63: | |
| return 9 | |
| } | |
| return 10 | |
| } | |
| // EncodeFixed64 writes a 64-bit integer to the Buffer. | |
| // This is the format for the | |
| // fixed64, sfixed64, and double protocol buffer types. | |
| func (p *Buffer) EncodeFixed64(x uint64) error { | |
| p.buf = append(p.buf, | |
| uint8(x), | |
| uint8(x>>8), | |
| uint8(x>>16), | |
| uint8(x>>24), | |
| uint8(x>>32), | |
| uint8(x>>40), | |
| uint8(x>>48), | |
| uint8(x>>56)) | |
| return nil | |
| } | |
| // EncodeFixed32 writes a 32-bit integer to the Buffer. | |
| // This is the format for the | |
| // fixed32, sfixed32, and float protocol buffer types. | |
| func (p *Buffer) EncodeFixed32(x uint64) error { | |
| p.buf = append(p.buf, | |
| uint8(x), | |
| uint8(x>>8), | |
| uint8(x>>16), | |
| uint8(x>>24)) | |
| return nil | |
| } | |
| // EncodeZigzag64 writes a zigzag-encoded 64-bit integer | |
| // to the Buffer. | |
| // This is the format used for the sint64 protocol buffer type. | |
| func (p *Buffer) EncodeZigzag64(x uint64) error { | |
| // use signed number to get arithmetic right shift. | |
| return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) | |
| } | |
| // EncodeZigzag32 writes a zigzag-encoded 32-bit integer | |
| // to the Buffer. | |
| // This is the format used for the sint32 protocol buffer type. | |
| func (p *Buffer) EncodeZigzag32(x uint64) error { | |
| // use signed number to get arithmetic right shift. | |
| return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31)))) | |
| } | |
| // EncodeRawBytes writes a count-delimited byte buffer to the Buffer. | |
| // This is the format used for the bytes protocol buffer | |
| // type and for embedded messages. | |
| func (p *Buffer) EncodeRawBytes(b []byte) error { | |
| p.EncodeVarint(uint64(len(b))) | |
| p.buf = append(p.buf, b...) | |
| return nil | |
| } | |
| // EncodeStringBytes writes an encoded string to the Buffer. | |
| // This is the format used for the proto2 string type. | |
| func (p *Buffer) EncodeStringBytes(s string) error { | |
| p.EncodeVarint(uint64(len(s))) | |
| p.buf = append(p.buf, s...) | |
| return nil | |
| } | |
| // Marshaler is the interface representing objects that can marshal themselves. | |
| type Marshaler interface { | |
| Marshal() ([]byte, error) | |
| } | |
| // EncodeMessage writes the protocol buffer to the Buffer, | |
| // prefixed by a varint-encoded length. | |
| func (p *Buffer) EncodeMessage(pb Message) error { | |
| siz := Size(pb) | |
| sizVar := SizeVarint(uint64(siz)) | |
| p.grow(siz + sizVar) | |
| p.EncodeVarint(uint64(siz)) | |
| return p.Marshal(pb) | |
| } | |
| // All protocol buffer fields are nillable, but be careful. | |
| func isNil(v reflect.Value) bool { | |
| switch v.Kind() { | |
| case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: | |
| return v.IsNil() | |
| } | |
| return false | |
| } |