| // 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" |
| "fmt" |
| "reflect" |
| ) |
| |
| // RequiredNotSetError is the error returned if Marshal is called with |
| // a protocol buffer struct whose required fields have not |
| // all been initialized. It is also the error returned if Unmarshal is |
| // called with an encoded protocol buffer that does not include all the |
| // required fields. |
| // |
| // When printed, RequiredNotSetError reports the first unset required field in a |
| // message. If the field cannot be precisely determined, it is reported as |
| // "{Unknown}". |
| type RequiredNotSetError struct { |
| field string |
| } |
| |
| func (e *RequiredNotSetError) Error() string { |
| return fmt.Sprintf("proto: required field %q not set", e.field) |
| } |
| |
| 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) |
| 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 |
| } |