| // Go support for Protocol Buffers - Google's data interchange format | |
| // | |
| // Copyright 2010 The Go Authors. All rights reserved. | |
| // http://code.google.com/p/goprotobuf/ | |
| // | |
| // 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(t.Elem(), 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(t.Elem(), 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 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 | |
| } | |
| // 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 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 | |
| } | |
| // 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 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 | |
| } | |
| // 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 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 | |
| } | |
| // 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 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 | |
| } | |
| // 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.stype, 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.stype, 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.stype, 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.stype, 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 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 | |
| } | |
| // 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.stype, 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.stype, 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.stype, 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.stype, 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 struct. | |
| func (o *Buffer) enc_struct(t reflect.Type, prop *StructProperties, base structPointer) error { | |
| var state errorState | |
| // Encode fields in tag order so that decoders may use optimizations | |
| // that depend on the ordering. | |
| // http://code.google.com/apis/protocolbuffers/docs/encoding.html#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(t reflect.Type, 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(t reflect.Type, prop *StructProperties, base structPointer, 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 := o.enc_struct(t, prop, base) | |
| 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 | |
| } |