| // 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" |
| "sort" |
| ) |
| |
| // 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") |
| |
| // ErrNil is the error returned if Marshal is called with nil. |
| ErrNil = errors.New("proto: Marshal called with nil") |
| ) |
| |
| // 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 |
| } |
| |
| func sizeVarint(x uint64) (n int) { |
| for { |
| n++ |
| x >>= 7 |
| if x == 0 { |
| break |
| } |
| } |
| return n |
| } |
| |
| // 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 |
| } |
| |
| func sizeFixed64(x uint64) int { |
| return 8 |
| } |
| |
| // 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 |
| } |
| |
| func sizeFixed32(x uint64) int { |
| return 4 |
| } |
| |
| // 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)))) |
| } |
| |
| func sizeZigzag64(x uint64) int { |
| return sizeVarint(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)))) |
| } |
| |
| func sizeZigzag32(x uint64) int { |
| return sizeVarint(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 |
| } |
| |
| func sizeRawBytes(b []byte) int { |
| return sizeVarint(uint64(len(b))) + |
| len(b) |
| } |
| |
| // 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 |
| } |
| |
| func sizeStringBytes(s string) int { |
| return sizeVarint(uint64(len(s))) + |
| len(s) |
| } |
| |
| // Marshaler is the interface representing objects that can marshal themselves. |
| type Marshaler interface { |
| Marshal() ([]byte, error) |
| } |
| |
| // Marshal takes the protocol buffer |
| // and encodes it into the wire format, returning the data. |
| func Marshal(pb Message) ([]byte, error) { |
| // Can the object marshal itself? |
| if m, ok := pb.(Marshaler); ok { |
| return m.Marshal() |
| } |
| p := NewBuffer(nil) |
| err := p.Marshal(pb) |
| var state errorState |
| if err != nil && !state.shouldContinue(err, nil) { |
| return nil, err |
| } |
| if p.buf == nil && err == nil { |
| // Return a non-nil slice on success. |
| return []byte{}, nil |
| } |
| return p.buf, err |
| } |
| |
| // Marshal takes the protocol buffer |
| // and encodes it into the wire format, writing the result to the |
| // Buffer. |
| func (p *Buffer) Marshal(pb Message) error { |
| // Can the object marshal itself? |
| if m, ok := pb.(Marshaler); ok { |
| data, err := m.Marshal() |
| if err != nil { |
| return err |
| } |
| p.buf = append(p.buf, data...) |
| return nil |
| } |
| |
| t, base, err := getbase(pb) |
| if structPointer_IsNil(base) { |
| return ErrNil |
| } |
| if err == nil { |
| err = p.enc_struct(GetProperties(t.Elem()), base) |
| } |
| |
| if collectStats { |
| stats.Encode++ |
| } |
| |
| return err |
| } |
| |
| // Size returns the encoded size of a protocol buffer. |
| func Size(pb Message) (n int) { |
| // Can the object marshal itself? If so, Size is slow. |
| // TODO: add Size to Marshaler, or add a Sizer interface. |
| if m, ok := pb.(Marshaler); ok { |
| b, _ := m.Marshal() |
| return len(b) |
| } |
| |
| t, base, err := getbase(pb) |
| if structPointer_IsNil(base) { |
| return 0 |
| } |
| if err == nil { |
| n = size_struct(GetProperties(t.Elem()), base) |
| } |
| |
| if collectStats { |
| stats.Size++ |
| } |
| |
| return |
| } |
| |
| // Individual type encoders. |
| |
| // Encode a bool. |
| func (o *Buffer) enc_bool(p *Properties, base structPointer) error { |
| v := *structPointer_Bool(base, p.field) |
| if v == nil { |
| return ErrNil |
| } |
| x := 0 |
| if *v { |
| x = 1 |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, uint64(x)) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error { |
| v := *structPointer_BoolVal(base, p.field) |
| if !v { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, 1) |
| return nil |
| } |
| |
| func size_bool(p *Properties, base structPointer) int { |
| v := *structPointer_Bool(base, p.field) |
| if v == nil { |
| return 0 |
| } |
| return len(p.tagcode) + 1 // each bool takes exactly one byte |
| } |
| |
| func size_proto3_bool(p *Properties, base structPointer) int { |
| v := *structPointer_BoolVal(base, p.field) |
| if !v { |
| return 0 |
| } |
| return len(p.tagcode) + 1 // each bool takes exactly one byte |
| } |
| |
| // Encode an int32. |
| func (o *Buffer) enc_int32(p *Properties, base structPointer) error { |
| v := structPointer_Word32(base, p.field) |
| if word32_IsNil(v) { |
| return ErrNil |
| } |
| x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, uint64(x)) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error { |
| v := structPointer_Word32Val(base, p.field) |
| x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range |
| if x == 0 { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, uint64(x)) |
| return nil |
| } |
| |
| func size_int32(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word32(base, p.field) |
| if word32_IsNil(v) { |
| return 0 |
| } |
| x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range |
| n += len(p.tagcode) |
| n += p.valSize(uint64(x)) |
| return |
| } |
| |
| func size_proto3_int32(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word32Val(base, p.field) |
| x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range |
| if x == 0 { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += p.valSize(uint64(x)) |
| return |
| } |
| |
| // Encode a uint32. |
| // Exactly the same as int32, except for no sign extension. |
| func (o *Buffer) enc_uint32(p *Properties, base structPointer) error { |
| v := structPointer_Word32(base, p.field) |
| if word32_IsNil(v) { |
| return ErrNil |
| } |
| x := word32_Get(v) |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, uint64(x)) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error { |
| v := structPointer_Word32Val(base, p.field) |
| x := word32Val_Get(v) |
| if x == 0 { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, uint64(x)) |
| return nil |
| } |
| |
| func size_uint32(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word32(base, p.field) |
| if word32_IsNil(v) { |
| return 0 |
| } |
| x := word32_Get(v) |
| n += len(p.tagcode) |
| n += p.valSize(uint64(x)) |
| return |
| } |
| |
| func size_proto3_uint32(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word32Val(base, p.field) |
| x := word32Val_Get(v) |
| if x == 0 { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += p.valSize(uint64(x)) |
| return |
| } |
| |
| // Encode an int64. |
| func (o *Buffer) enc_int64(p *Properties, base structPointer) error { |
| v := structPointer_Word64(base, p.field) |
| if word64_IsNil(v) { |
| return ErrNil |
| } |
| x := word64_Get(v) |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, x) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error { |
| v := structPointer_Word64Val(base, p.field) |
| x := word64Val_Get(v) |
| if x == 0 { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, x) |
| return nil |
| } |
| |
| func size_int64(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word64(base, p.field) |
| if word64_IsNil(v) { |
| return 0 |
| } |
| x := word64_Get(v) |
| n += len(p.tagcode) |
| n += p.valSize(x) |
| return |
| } |
| |
| func size_proto3_int64(p *Properties, base structPointer) (n int) { |
| v := structPointer_Word64Val(base, p.field) |
| x := word64Val_Get(v) |
| if x == 0 { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += p.valSize(x) |
| return |
| } |
| |
| // Encode a string. |
| func (o *Buffer) enc_string(p *Properties, base structPointer) error { |
| v := *structPointer_String(base, p.field) |
| if v == nil { |
| return ErrNil |
| } |
| x := *v |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeStringBytes(x) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error { |
| v := *structPointer_StringVal(base, p.field) |
| if v == "" { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeStringBytes(v) |
| return nil |
| } |
| |
| func size_string(p *Properties, base structPointer) (n int) { |
| v := *structPointer_String(base, p.field) |
| if v == nil { |
| return 0 |
| } |
| x := *v |
| n += len(p.tagcode) |
| n += sizeStringBytes(x) |
| return |
| } |
| |
| func size_proto3_string(p *Properties, base structPointer) (n int) { |
| v := *structPointer_StringVal(base, p.field) |
| if v == "" { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += sizeStringBytes(v) |
| return |
| } |
| |
| // 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 |
| } |
| |
| // Encode a message struct. |
| func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error { |
| var state errorState |
| structp := structPointer_GetStructPointer(base, p.field) |
| if structPointer_IsNil(structp) { |
| return ErrNil |
| } |
| |
| // Can the object marshal itself? |
| if p.isMarshaler { |
| m := structPointer_Interface(structp, p.stype).(Marshaler) |
| data, err := m.Marshal() |
| if err != nil && !state.shouldContinue(err, nil) { |
| return err |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeRawBytes(data) |
| return nil |
| } |
| |
| o.buf = append(o.buf, p.tagcode...) |
| return o.enc_len_struct(p.sprop, structp, &state) |
| } |
| |
| func size_struct_message(p *Properties, base structPointer) int { |
| structp := structPointer_GetStructPointer(base, p.field) |
| if structPointer_IsNil(structp) { |
| return 0 |
| } |
| |
| // Can the object marshal itself? |
| if p.isMarshaler { |
| m := structPointer_Interface(structp, p.stype).(Marshaler) |
| data, _ := m.Marshal() |
| n0 := len(p.tagcode) |
| n1 := sizeRawBytes(data) |
| return n0 + n1 |
| } |
| |
| n0 := len(p.tagcode) |
| n1 := size_struct(p.sprop, structp) |
| n2 := sizeVarint(uint64(n1)) // size of encoded length |
| return n0 + n1 + n2 |
| } |
| |
| // Encode a group struct. |
| func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error { |
| var state errorState |
| b := structPointer_GetStructPointer(base, p.field) |
| if structPointer_IsNil(b) { |
| return ErrNil |
| } |
| |
| o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) |
| err := o.enc_struct(p.sprop, b) |
| if err != nil && !state.shouldContinue(err, nil) { |
| return err |
| } |
| o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) |
| return state.err |
| } |
| |
| func size_struct_group(p *Properties, base structPointer) (n int) { |
| b := structPointer_GetStructPointer(base, p.field) |
| if structPointer_IsNil(b) { |
| return 0 |
| } |
| |
| n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup)) |
| n += size_struct(p.sprop, b) |
| n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup)) |
| return |
| } |
| |
| // Encode a slice of bools ([]bool). |
| func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error { |
| s := *structPointer_BoolSlice(base, p.field) |
| l := len(s) |
| if l == 0 { |
| return ErrNil |
| } |
| for _, x := range s { |
| o.buf = append(o.buf, p.tagcode...) |
| v := uint64(0) |
| if x { |
| v = 1 |
| } |
| p.valEnc(o, v) |
| } |
| return nil |
| } |
| |
| func size_slice_bool(p *Properties, base structPointer) int { |
| s := *structPointer_BoolSlice(base, p.field) |
| l := len(s) |
| if l == 0 { |
| return 0 |
| } |
| return l * (len(p.tagcode) + 1) // each bool takes exactly one byte |
| } |
| |
| // Encode a slice of bools ([]bool) in packed format. |
| func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error { |
| s := *structPointer_BoolSlice(base, p.field) |
| l := len(s) |
| if l == 0 { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeVarint(uint64(l)) // each bool takes exactly one byte |
| for _, x := range s { |
| v := uint64(0) |
| if x { |
| v = 1 |
| } |
| p.valEnc(o, v) |
| } |
| return nil |
| } |
| |
| func size_slice_packed_bool(p *Properties, base structPointer) (n int) { |
| s := *structPointer_BoolSlice(base, p.field) |
| l := len(s) |
| if l == 0 { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += sizeVarint(uint64(l)) |
| n += l // each bool takes exactly one byte |
| return |
| } |
| |
| // Encode a slice of bytes ([]byte). |
| func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error { |
| s := *structPointer_Bytes(base, p.field) |
| if s == nil { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeRawBytes(s) |
| return nil |
| } |
| |
| func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error { |
| s := *structPointer_Bytes(base, p.field) |
| if len(s) == 0 { |
| return ErrNil |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeRawBytes(s) |
| return nil |
| } |
| |
| func size_slice_byte(p *Properties, base structPointer) (n int) { |
| s := *structPointer_Bytes(base, p.field) |
| if s == nil { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += sizeRawBytes(s) |
| return |
| } |
| |
| func size_proto3_slice_byte(p *Properties, base structPointer) (n int) { |
| s := *structPointer_Bytes(base, p.field) |
| if len(s) == 0 { |
| return 0 |
| } |
| n += len(p.tagcode) |
| n += sizeRawBytes(s) |
| return |
| } |
| |
| // Encode a slice of int32s ([]int32). |
| func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| for i := 0; i < l; i++ { |
| o.buf = append(o.buf, p.tagcode...) |
| x := int32(s.Index(i)) // permit sign extension to use full 64-bit range |
| p.valEnc(o, uint64(x)) |
| } |
| return nil |
| } |
| |
| func size_slice_int32(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| for i := 0; i < l; i++ { |
| n += len(p.tagcode) |
| x := int32(s.Index(i)) // permit sign extension to use full 64-bit range |
| n += p.valSize(uint64(x)) |
| } |
| return |
| } |
| |
| // Encode a slice of int32s ([]int32) in packed format. |
| func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| // TODO: Reuse a Buffer. |
| buf := NewBuffer(nil) |
| for i := 0; i < l; i++ { |
| x := int32(s.Index(i)) // permit sign extension to use full 64-bit range |
| p.valEnc(buf, uint64(x)) |
| } |
| |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeVarint(uint64(len(buf.buf))) |
| o.buf = append(o.buf, buf.buf...) |
| return nil |
| } |
| |
| func size_slice_packed_int32(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| var bufSize int |
| for i := 0; i < l; i++ { |
| x := int32(s.Index(i)) // permit sign extension to use full 64-bit range |
| bufSize += p.valSize(uint64(x)) |
| } |
| |
| n += len(p.tagcode) |
| n += sizeVarint(uint64(bufSize)) |
| n += bufSize |
| return |
| } |
| |
| // Encode a slice of uint32s ([]uint32). |
| // Exactly the same as int32, except for no sign extension. |
| func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| for i := 0; i < l; i++ { |
| o.buf = append(o.buf, p.tagcode...) |
| x := s.Index(i) |
| p.valEnc(o, uint64(x)) |
| } |
| return nil |
| } |
| |
| func size_slice_uint32(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| for i := 0; i < l; i++ { |
| n += len(p.tagcode) |
| x := s.Index(i) |
| n += p.valSize(uint64(x)) |
| } |
| return |
| } |
| |
| // Encode a slice of uint32s ([]uint32) in packed format. |
| // Exactly the same as int32, except for no sign extension. |
| func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| // TODO: Reuse a Buffer. |
| buf := NewBuffer(nil) |
| for i := 0; i < l; i++ { |
| p.valEnc(buf, uint64(s.Index(i))) |
| } |
| |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeVarint(uint64(len(buf.buf))) |
| o.buf = append(o.buf, buf.buf...) |
| return nil |
| } |
| |
| func size_slice_packed_uint32(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word32Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| var bufSize int |
| for i := 0; i < l; i++ { |
| bufSize += p.valSize(uint64(s.Index(i))) |
| } |
| |
| n += len(p.tagcode) |
| n += sizeVarint(uint64(bufSize)) |
| n += bufSize |
| return |
| } |
| |
| // Encode a slice of int64s ([]int64). |
| func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error { |
| s := structPointer_Word64Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| for i := 0; i < l; i++ { |
| o.buf = append(o.buf, p.tagcode...) |
| p.valEnc(o, s.Index(i)) |
| } |
| return nil |
| } |
| |
| func size_slice_int64(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word64Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| for i := 0; i < l; i++ { |
| n += len(p.tagcode) |
| n += p.valSize(s.Index(i)) |
| } |
| return |
| } |
| |
| // Encode a slice of int64s ([]int64) in packed format. |
| func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error { |
| s := structPointer_Word64Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return ErrNil |
| } |
| // TODO: Reuse a Buffer. |
| buf := NewBuffer(nil) |
| for i := 0; i < l; i++ { |
| p.valEnc(buf, s.Index(i)) |
| } |
| |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeVarint(uint64(len(buf.buf))) |
| o.buf = append(o.buf, buf.buf...) |
| return nil |
| } |
| |
| func size_slice_packed_int64(p *Properties, base structPointer) (n int) { |
| s := structPointer_Word64Slice(base, p.field) |
| l := s.Len() |
| if l == 0 { |
| return 0 |
| } |
| var bufSize int |
| for i := 0; i < l; i++ { |
| bufSize += p.valSize(s.Index(i)) |
| } |
| |
| n += len(p.tagcode) |
| n += sizeVarint(uint64(bufSize)) |
| n += bufSize |
| return |
| } |
| |
| // Encode a slice of slice of bytes ([][]byte). |
| func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error { |
| ss := *structPointer_BytesSlice(base, p.field) |
| l := len(ss) |
| if l == 0 { |
| return ErrNil |
| } |
| for i := 0; i < l; i++ { |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeRawBytes(ss[i]) |
| } |
| return nil |
| } |
| |
| func size_slice_slice_byte(p *Properties, base structPointer) (n int) { |
| ss := *structPointer_BytesSlice(base, p.field) |
| l := len(ss) |
| if l == 0 { |
| return 0 |
| } |
| n += l * len(p.tagcode) |
| for i := 0; i < l; i++ { |
| n += sizeRawBytes(ss[i]) |
| } |
| return |
| } |
| |
| // Encode a slice of strings ([]string). |
| func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error { |
| ss := *structPointer_StringSlice(base, p.field) |
| l := len(ss) |
| for i := 0; i < l; i++ { |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeStringBytes(ss[i]) |
| } |
| return nil |
| } |
| |
| func size_slice_string(p *Properties, base structPointer) (n int) { |
| ss := *structPointer_StringSlice(base, p.field) |
| l := len(ss) |
| n += l * len(p.tagcode) |
| for i := 0; i < l; i++ { |
| n += sizeStringBytes(ss[i]) |
| } |
| return |
| } |
| |
| // Encode a slice of message structs ([]*struct). |
| func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error { |
| var state errorState |
| s := structPointer_StructPointerSlice(base, p.field) |
| l := s.Len() |
| |
| for i := 0; i < l; i++ { |
| structp := s.Index(i) |
| if structPointer_IsNil(structp) { |
| return ErrRepeatedHasNil |
| } |
| |
| // Can the object marshal itself? |
| if p.isMarshaler { |
| m := structPointer_Interface(structp, p.stype).(Marshaler) |
| data, err := m.Marshal() |
| if err != nil && !state.shouldContinue(err, nil) { |
| return err |
| } |
| o.buf = append(o.buf, p.tagcode...) |
| o.EncodeRawBytes(data) |
| continue |
| } |
| |
| o.buf = append(o.buf, p.tagcode...) |
| err := o.enc_len_struct(p.sprop, structp, &state) |
| if err != nil && !state.shouldContinue(err, nil) { |
| if err == ErrNil { |
| return ErrRepeatedHasNil |
| } |
| return err |
| } |
| } |
| return state.err |
| } |
| |
| func size_slice_struct_message(p *Properties, base structPointer) (n int) { |
| s := structPointer_StructPointerSlice(base, p.field) |
| l := s.Len() |
| n += l * len(p.tagcode) |
| for i := 0; i < l; i++ { |
| structp := s.Index(i) |
| if structPointer_IsNil(structp) { |
| return // return the size up to this point |
| } |
| |
| // Can the object marshal itself? |
| if p.isMarshaler { |
| m := structPointer_Interface(structp, p.stype).(Marshaler) |
| data, _ := m.Marshal() |
| n += len(p.tagcode) |
| n += sizeRawBytes(data) |
| continue |
| } |
| |
| n0 := size_struct(p.sprop, structp) |
| n1 := sizeVarint(uint64(n0)) // size of encoded length |
| n += n0 + n1 |
| } |
| return |
| } |
| |
| // Encode a slice of group structs ([]*struct). |
| func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error { |
| var state errorState |
| s := structPointer_StructPointerSlice(base, p.field) |
| l := s.Len() |
| |
| for i := 0; i < l; i++ { |
| b := s.Index(i) |
| if structPointer_IsNil(b) { |
| return ErrRepeatedHasNil |
| } |
| |
| o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup)) |
| |
| err := o.enc_struct(p.sprop, b) |
| |
| if err != nil && !state.shouldContinue(err, nil) { |
| if err == ErrNil { |
| return ErrRepeatedHasNil |
| } |
| return err |
| } |
| |
| o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup)) |
| } |
| return state.err |
| } |
| |
| func size_slice_struct_group(p *Properties, base structPointer) (n int) { |
| s := structPointer_StructPointerSlice(base, p.field) |
| l := s.Len() |
| |
| n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup)) |
| n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup)) |
| for i := 0; i < l; i++ { |
| b := s.Index(i) |
| if structPointer_IsNil(b) { |
| return // return size up to this point |
| } |
| |
| n += size_struct(p.sprop, b) |
| } |
| return |
| } |
| |
| // Encode an extension map. |
| func (o *Buffer) enc_map(p *Properties, base structPointer) error { |
| v := *structPointer_ExtMap(base, p.field) |
| if err := encodeExtensionMap(v); err != nil { |
| return err |
| } |
| // Fast-path for common cases: zero or one extensions. |
| if len(v) <= 1 { |
| for _, e := range v { |
| o.buf = append(o.buf, e.enc...) |
| } |
| return nil |
| } |
| |
| // Sort keys to provide a deterministic encoding. |
| keys := make([]int, 0, len(v)) |
| for k := range v { |
| keys = append(keys, int(k)) |
| } |
| sort.Ints(keys) |
| |
| for _, k := range keys { |
| o.buf = append(o.buf, v[int32(k)].enc...) |
| } |
| return nil |
| } |
| |
| func size_map(p *Properties, base structPointer) int { |
| v := *structPointer_ExtMap(base, p.field) |
| return sizeExtensionMap(v) |
| } |
| |
| // Encode a map field. |
| func (o *Buffer) enc_new_map(p *Properties, base structPointer) error { |
| var state errorState // XXX: or do we need to plumb this through? |
| |
| /* |
| A map defined as |
| map<key_type, value_type> map_field = N; |
| is encoded in the same way as |
| message MapFieldEntry { |
| key_type key = 1; |
| value_type value = 2; |
| } |
| repeated MapFieldEntry map_field = N; |
| */ |
| |
| v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V |
| if v.Len() == 0 { |
| return nil |
| } |
| |
| keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) |
| |
| enc := func() error { |
| if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil { |
| return err |
| } |
| if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| keys := v.MapKeys() |
| sort.Sort(mapKeys(keys)) |
| for _, key := range keys { |
| val := v.MapIndex(key) |
| |
| keycopy.Set(key) |
| valcopy.Set(val) |
| |
| o.buf = append(o.buf, p.tagcode...) |
| if err := o.enc_len_thing(enc, &state); err != nil { |
| return err |
| } |
| } |
| return nil |
| } |
| |
| func size_new_map(p *Properties, base structPointer) int { |
| v := structPointer_Map(base, p.field, p.mtype).Elem() // map[K]V |
| |
| keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype) |
| |
| n := 0 |
| for _, key := range v.MapKeys() { |
| val := v.MapIndex(key) |
| keycopy.Set(key) |
| valcopy.Set(val) |
| |
| // Tag codes are two bytes per map entry. |
| n += 2 |
| n += p.mkeyprop.size(p.mkeyprop, keybase) |
| n += p.mvalprop.size(p.mvalprop, valbase) |
| } |
| return n |
| } |
| |
| // mapEncodeScratch returns a new reflect.Value matching the map's value type, |
| // and a structPointer suitable for passing to an encoder or sizer. |
| func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) { |
| // Prepare addressable doubly-indirect placeholders for the key and value types. |
| // This is needed because the element-type encoders expect **T, but the map iteration produces T. |
| |
| keycopy = reflect.New(mapType.Key()).Elem() // addressable K |
| keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K |
| keyptr.Set(keycopy.Addr()) // |
| keybase = toStructPointer(keyptr.Addr()) // **K |
| |
| // Value types are more varied and require special handling. |
| switch mapType.Elem().Kind() { |
| case reflect.Slice: |
| // []byte |
| var dummy []byte |
| valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte |
| valbase = toStructPointer(valcopy.Addr()) |
| case reflect.Ptr: |
| // message; the generated field type is map[K]*Msg (so V is *Msg), |
| // so we only need one level of indirection. |
| valcopy = reflect.New(mapType.Elem()).Elem() // addressable V |
| valbase = toStructPointer(valcopy.Addr()) |
| default: |
| // everything else |
| valcopy = reflect.New(mapType.Elem()).Elem() // addressable V |
| valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V |
| valptr.Set(valcopy.Addr()) // |
| valbase = toStructPointer(valptr.Addr()) // **V |
| } |
| return |
| } |
| |
| // Encode a struct. |
| func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error { |
| var state errorState |
| // Encode fields in tag order so that decoders may use optimizations |
| // that depend on the ordering. |
| // https://developers.google.com/protocol-buffers/docs/encoding#order |
| for _, i := range prop.order { |
| p := prop.Prop[i] |
| if p.enc != nil { |
| err := p.enc(o, p, base) |
| if err != nil { |
| if err == ErrNil { |
| if p.Required && state.err == nil { |
| state.err = &RequiredNotSetError{p.Name} |
| } |
| } else if !state.shouldContinue(err, p) { |
| return err |
| } |
| } |
| } |
| } |
| |
| // Add unrecognized fields at the end. |
| if prop.unrecField.IsValid() { |
| v := *structPointer_Bytes(base, prop.unrecField) |
| if len(v) > 0 { |
| o.buf = append(o.buf, v...) |
| } |
| } |
| |
| return state.err |
| } |
| |
| func size_struct(prop *StructProperties, base structPointer) (n int) { |
| for _, i := range prop.order { |
| p := prop.Prop[i] |
| if p.size != nil { |
| n += p.size(p, base) |
| } |
| } |
| |
| // Add unrecognized fields at the end. |
| if prop.unrecField.IsValid() { |
| v := *structPointer_Bytes(base, prop.unrecField) |
| n += len(v) |
| } |
| |
| return |
| } |
| |
| var zeroes [20]byte // longer than any conceivable sizeVarint |
| |
| // Encode a struct, preceded by its encoded length (as a varint). |
| func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error { |
| return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state) |
| } |
| |
| // Encode something, preceded by its encoded length (as a varint). |
| func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error { |
| iLen := len(o.buf) |
| o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length |
| iMsg := len(o.buf) |
| err := enc() |
| if err != nil && !state.shouldContinue(err, nil) { |
| return err |
| } |
| lMsg := len(o.buf) - iMsg |
| lLen := sizeVarint(uint64(lMsg)) |
| switch x := lLen - (iMsg - iLen); { |
| case x > 0: // actual length is x bytes larger than the space we reserved |
| // Move msg x bytes right. |
| o.buf = append(o.buf, zeroes[:x]...) |
| copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) |
| case x < 0: // actual length is x bytes smaller than the space we reserved |
| // Move msg x bytes left. |
| copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg]) |
| o.buf = o.buf[:len(o.buf)+x] // x is negative |
| } |
| // Encode the length in the reserved space. |
| o.buf = o.buf[:iLen] |
| o.EncodeVarint(uint64(lMsg)) |
| o.buf = o.buf[:len(o.buf)+lMsg] |
| return state.err |
| } |
| |
| // errorState maintains the first error that occurs and updates that error |
| // with additional context. |
| type errorState struct { |
| err error |
| } |
| |
| // shouldContinue reports whether encoding should continue upon encountering the |
| // given error. If the error is RequiredNotSetError, shouldContinue returns true |
| // and, if this is the first appearance of that error, remembers it for future |
| // reporting. |
| // |
| // If prop is not nil, it may update any error with additional context about the |
| // field with the error. |
| func (s *errorState) shouldContinue(err error, prop *Properties) bool { |
| // Ignore unset required fields. |
| reqNotSet, ok := err.(*RequiredNotSetError) |
| if !ok { |
| return false |
| } |
| if s.err == nil { |
| if prop != nil { |
| err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field} |
| } |
| s.err = err |
| } |
| return true |
| } |