mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #833 from unihorn/99
bump(code.google.com/p/gogoprotobuf): 7fd1620f09
This commit is contained in:
commit
3455431da3
@ -83,9 +83,14 @@ func mergeStruct(out, in reflect.Value) {
|
|||||||
mergeAny(out.Field(i), in.Field(i))
|
mergeAny(out.Field(i), in.Field(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
if emIn, ok := in.Addr().Interface().(extendableProto); ok {
|
if emIn, ok := in.Addr().Interface().(extensionsMap); ok {
|
||||||
emOut := out.Addr().Interface().(extendableProto)
|
emOut := out.Addr().Interface().(extensionsMap)
|
||||||
mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap())
|
mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap())
|
||||||
|
} else if emIn, ok := in.Addr().Interface().(extensionsBytes); ok {
|
||||||
|
emOut := out.Addr().Interface().(extensionsBytes)
|
||||||
|
bIn := emIn.GetExtensions()
|
||||||
|
bOut := emOut.GetExtensions()
|
||||||
|
*bOut = append(*bOut, *bIn...)
|
||||||
}
|
}
|
||||||
|
|
||||||
uf := in.FieldByName("XXX_unrecognized")
|
uf := in.FieldByName("XXX_unrecognized")
|
||||||
|
@ -235,12 +235,6 @@ func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer,
|
|||||||
|
|
||||||
ptr := structPointer_Bytes(base, unrecField)
|
ptr := structPointer_Bytes(base, unrecField)
|
||||||
|
|
||||||
if *ptr == nil {
|
|
||||||
// This is the first skipped element,
|
|
||||||
// allocate a new buffer.
|
|
||||||
*ptr = o.bufalloc()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the skipped field to struct field
|
// Add the skipped field to struct field
|
||||||
obuf := o.buf
|
obuf := o.buf
|
||||||
|
|
||||||
@ -381,9 +375,14 @@ func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group
|
|||||||
if prop.extendable {
|
if prop.extendable {
|
||||||
if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) {
|
if e := structPointer_Interface(base, st).(extendableProto); isExtensionField(e, int32(tag)) {
|
||||||
if err = o.skip(st, tag, wire); err == nil {
|
if err = o.skip(st, tag, wire); err == nil {
|
||||||
ext := e.ExtensionMap()[int32(tag)] // may be missing
|
if ee, ok := e.(extensionsMap); ok {
|
||||||
|
ext := ee.ExtensionMap()[int32(tag)] // may be missing
|
||||||
ext.enc = append(ext.enc, o.buf[oi:o.index]...)
|
ext.enc = append(ext.enc, o.buf[oi:o.index]...)
|
||||||
e.ExtensionMap()[int32(tag)] = ext
|
ee.ExtensionMap()[int32(tag)] = ext
|
||||||
|
} else if ee, ok := e.(extensionsBytes); ok {
|
||||||
|
ext := ee.GetExtensions()
|
||||||
|
*ext = append(*ext, o.buf[oi:o.index]...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -221,6 +221,10 @@ func Marshal(pb Message) ([]byte, error) {
|
|||||||
if err != nil && !state.shouldContinue(err, nil) {
|
if err != nil && !state.shouldContinue(err, nil) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if p.buf == nil && err == nil {
|
||||||
|
// Return a non-nil slice on success.
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
return p.buf, err
|
return p.buf, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,23 +404,8 @@ func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// need the length before we can write out the message itself,
|
|
||||||
// so marshal into a separate byte buffer first.
|
|
||||||
obuf := o.buf
|
|
||||||
o.buf = o.bufalloc()
|
|
||||||
|
|
||||||
err := o.enc_struct(p.stype, p.sprop, structp)
|
|
||||||
|
|
||||||
nbuf := o.buf
|
|
||||||
o.buf = obuf
|
|
||||||
if err != nil && !state.shouldContinue(err, nil) {
|
|
||||||
o.buffree(nbuf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.buf = append(o.buf, p.tagcode...)
|
o.buf = append(o.buf, p.tagcode...)
|
||||||
o.EncodeRawBytes(nbuf)
|
return o.enc_len_struct(p.stype, p.sprop, structp, &state)
|
||||||
o.buffree(nbuf)
|
|
||||||
return state.err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func size_struct_message(p *Properties, base structPointer) int {
|
func size_struct_message(p *Properties, base structPointer) int {
|
||||||
@ -748,24 +737,14 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
obuf := o.buf
|
o.buf = append(o.buf, p.tagcode...)
|
||||||
o.buf = o.bufalloc()
|
err := o.enc_len_struct(p.stype, p.sprop, structp, &state)
|
||||||
|
|
||||||
err := o.enc_struct(p.stype, p.sprop, structp)
|
|
||||||
|
|
||||||
nbuf := o.buf
|
|
||||||
o.buf = obuf
|
|
||||||
if err != nil && !state.shouldContinue(err, nil) {
|
if err != nil && !state.shouldContinue(err, nil) {
|
||||||
o.buffree(nbuf)
|
|
||||||
if err == ErrNil {
|
if err == ErrNil {
|
||||||
return ErrRepeatedHasNil
|
return ErrRepeatedHasNil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.buf = append(o.buf, p.tagcode...)
|
|
||||||
o.EncodeRawBytes(nbuf)
|
|
||||||
|
|
||||||
o.buffree(nbuf)
|
|
||||||
}
|
}
|
||||||
return state.err
|
return state.err
|
||||||
}
|
}
|
||||||
@ -923,6 +902,36 @@ func size_struct(t reflect.Type, prop *StructProperties, base structPointer) (n
|
|||||||
return
|
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
|
// errorState maintains the first error that occurs and updates that error
|
||||||
// with additional context.
|
// with additional context.
|
||||||
type errorState struct {
|
type errorState struct {
|
||||||
|
@ -44,6 +44,24 @@ type Sizer interface {
|
|||||||
Size() int
|
Size() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Buffer) enc_ext_slice_byte(p *Properties, base structPointer) error {
|
||||||
|
s := *structPointer_Bytes(base, p.field)
|
||||||
|
if s == nil {
|
||||||
|
return ErrNil
|
||||||
|
}
|
||||||
|
o.buf = append(o.buf, s...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func size_ext_slice_byte(p *Properties, base structPointer) (n int) {
|
||||||
|
s := *structPointer_Bytes(base, p.field)
|
||||||
|
if s == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
n += len(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Encode a reference to bool pointer.
|
// Encode a reference to bool pointer.
|
||||||
func (o *Buffer) enc_ref_bool(p *Properties, base structPointer) error {
|
func (o *Buffer) enc_ref_bool(p *Properties, base structPointer) error {
|
||||||
v := structPointer_RefBool(base, p.field)
|
v := structPointer_RefBool(base, p.field)
|
||||||
@ -156,23 +174,8 @@ func (o *Buffer) enc_ref_struct_message(p *Properties, base structPointer) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// need the length before we can write out the message itself,
|
|
||||||
// so marshal into a separate byte buffer first.
|
|
||||||
obuf := o.buf
|
|
||||||
o.buf = o.bufalloc()
|
|
||||||
|
|
||||||
err := o.enc_struct(p.stype, p.sprop, structp)
|
|
||||||
|
|
||||||
nbuf := o.buf
|
|
||||||
o.buf = obuf
|
|
||||||
if err != nil && !state.shouldContinue(err, nil) {
|
|
||||||
o.buffree(nbuf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
o.buf = append(o.buf, p.tagcode...)
|
o.buf = append(o.buf, p.tagcode...)
|
||||||
o.EncodeRawBytes(nbuf)
|
return o.enc_len_struct(p.stype, p.sprop, structp, &state)
|
||||||
o.buffree(nbuf)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO this is only copied, please fix this
|
//TODO this is only copied, please fix this
|
||||||
@ -222,26 +225,17 @@ func (o *Buffer) enc_slice_ref_struct_message(p *Properties, base structPointer)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
obuf := o.buf
|
o.buf = append(o.buf, p.tagcode...)
|
||||||
o.buf = o.bufalloc()
|
err := o.enc_len_struct(p.stype, p.sprop, structp, &state)
|
||||||
|
|
||||||
err := o.enc_struct(p.stype, p.sprop, structp)
|
|
||||||
|
|
||||||
nbuf := o.buf
|
|
||||||
o.buf = obuf
|
|
||||||
if err != nil && !state.shouldContinue(err, nil) {
|
if err != nil && !state.shouldContinue(err, nil) {
|
||||||
o.buffree(nbuf)
|
|
||||||
if err == ErrNil {
|
if err == ErrNil {
|
||||||
return ErrRepeatedHasNil
|
return ErrRepeatedHasNil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.buf = append(o.buf, p.tagcode...)
|
|
||||||
o.EncodeRawBytes(nbuf)
|
|
||||||
|
|
||||||
o.buffree(nbuf)
|
|
||||||
}
|
}
|
||||||
return nil
|
return state.err
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO this is only copied, please fix this
|
//TODO this is only copied, please fix this
|
||||||
|
@ -55,9 +55,18 @@ type ExtensionRange struct {
|
|||||||
type extendableProto interface {
|
type extendableProto interface {
|
||||||
Message
|
Message
|
||||||
ExtensionRangeArray() []ExtensionRange
|
ExtensionRangeArray() []ExtensionRange
|
||||||
|
}
|
||||||
|
|
||||||
|
type extensionsMap interface {
|
||||||
|
extendableProto
|
||||||
ExtensionMap() map[int32]Extension
|
ExtensionMap() map[int32]Extension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type extensionsBytes interface {
|
||||||
|
extendableProto
|
||||||
|
GetExtensions() *[]byte
|
||||||
|
}
|
||||||
|
|
||||||
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
|
var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
|
||||||
|
|
||||||
// ExtensionDesc represents an extension specification.
|
// ExtensionDesc represents an extension specification.
|
||||||
@ -92,7 +101,15 @@ type Extension struct {
|
|||||||
|
|
||||||
// SetRawExtension is for testing only.
|
// SetRawExtension is for testing only.
|
||||||
func SetRawExtension(base extendableProto, id int32, b []byte) {
|
func SetRawExtension(base extendableProto, id int32, b []byte) {
|
||||||
base.ExtensionMap()[id] = Extension{enc: b}
|
if ebase, ok := base.(extensionsMap); ok {
|
||||||
|
ebase.ExtensionMap()[id] = Extension{enc: b}
|
||||||
|
} else if ebase, ok := base.(extensionsBytes); ok {
|
||||||
|
clearExtension(base, id)
|
||||||
|
ext := ebase.GetExtensions()
|
||||||
|
*ext = append(*ext, b...)
|
||||||
|
} else {
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isExtensionField returns true iff the given field number is in an extension range.
|
// isExtensionField returns true iff the given field number is in an extension range.
|
||||||
@ -210,26 +227,80 @@ func sizeExtensionMap(m map[int32]Extension) (n int) {
|
|||||||
// HasExtension returns whether the given extension is present in pb.
|
// HasExtension returns whether the given extension is present in pb.
|
||||||
func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
|
func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
|
||||||
// TODO: Check types, field numbers, etc.?
|
// TODO: Check types, field numbers, etc.?
|
||||||
_, ok := pb.ExtensionMap()[extension.Field]
|
if epb, doki := pb.(extensionsMap); doki {
|
||||||
|
_, ok := epb.ExtensionMap()[extension.Field]
|
||||||
return ok
|
return ok
|
||||||
|
} else if epb, doki := pb.(extensionsBytes); doki {
|
||||||
|
ext := epb.GetExtensions()
|
||||||
|
buf := *ext
|
||||||
|
o := 0
|
||||||
|
for o < len(buf) {
|
||||||
|
tag, n := DecodeVarint(buf[o:])
|
||||||
|
fieldNum := int32(tag >> 3)
|
||||||
|
if int32(fieldNum) == extension.Field {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
wireType := int(tag & 0x7)
|
||||||
|
o += n
|
||||||
|
l, err := size(buf[o:], wireType)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
o += l
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteExtension(pb extensionsBytes, theFieldNum int32, offset int) int {
|
||||||
|
ext := pb.GetExtensions()
|
||||||
|
for offset < len(*ext) {
|
||||||
|
tag, n1 := DecodeVarint((*ext)[offset:])
|
||||||
|
fieldNum := int32(tag >> 3)
|
||||||
|
wireType := int(tag & 0x7)
|
||||||
|
n2, err := size((*ext)[offset+n1:], wireType)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
newOffset := offset + n1 + n2
|
||||||
|
if fieldNum == theFieldNum {
|
||||||
|
*ext = append((*ext)[:offset], (*ext)[newOffset:]...)
|
||||||
|
return offset
|
||||||
|
}
|
||||||
|
offset = newOffset
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearExtension(pb extendableProto, fieldNum int32) {
|
||||||
|
if epb, doki := pb.(extensionsMap); doki {
|
||||||
|
delete(epb.ExtensionMap(), fieldNum)
|
||||||
|
} else if epb, doki := pb.(extensionsBytes); doki {
|
||||||
|
offset := 0
|
||||||
|
for offset != -1 {
|
||||||
|
offset = deleteExtension(epb, fieldNum, offset)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearExtension removes the given extension from pb.
|
// ClearExtension removes the given extension from pb.
|
||||||
func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
|
func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
|
||||||
// TODO: Check types, field numbers, etc.?
|
// TODO: Check types, field numbers, etc.?
|
||||||
delete(pb.ExtensionMap(), extension.Field)
|
clearExtension(pb, extension.Field)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExtension parses and returns the given extension of pb.
|
// GetExtension parses and returns the given extension of pb.
|
||||||
// If the extension is not present it returns ErrMissingExtension.
|
// If the extension is not present it returns ErrMissingExtension.
|
||||||
// If the returned extension is modified, SetExtension must be called
|
|
||||||
// for the modifications to be reflected in pb.
|
|
||||||
func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
|
func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, error) {
|
||||||
if err := checkExtensionTypes(pb, extension); err != nil {
|
if err := checkExtensionTypes(pb, extension); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
e, ok := pb.ExtensionMap()[extension.Field]
|
if epb, doki := pb.(extensionsMap); doki {
|
||||||
|
e, ok := epb.ExtensionMap()[extension.Field]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ErrMissingExtension
|
return nil, ErrMissingExtension
|
||||||
}
|
}
|
||||||
@ -255,6 +326,28 @@ func GetExtension(pb extendableProto, extension *ExtensionDesc) (interface{}, er
|
|||||||
e.desc = extension
|
e.desc = extension
|
||||||
e.enc = nil
|
e.enc = nil
|
||||||
return e.value, nil
|
return e.value, nil
|
||||||
|
} else if epb, doki := pb.(extensionsBytes); doki {
|
||||||
|
ext := epb.GetExtensions()
|
||||||
|
o := 0
|
||||||
|
for o < len(*ext) {
|
||||||
|
tag, n := DecodeVarint((*ext)[o:])
|
||||||
|
fieldNum := int32(tag >> 3)
|
||||||
|
wireType := int(tag & 0x7)
|
||||||
|
l, err := size((*ext)[o+n:], wireType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if int32(fieldNum) == extension.Field {
|
||||||
|
v, err := decodeExtension((*ext)[o:o+n+l], extension)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
o += n + l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeExtension decodes an extension encoded in b.
|
// decodeExtension decodes an extension encoded in b.
|
||||||
@ -319,7 +412,21 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
|
|||||||
return errors.New("proto: bad extension value type")
|
return errors.New("proto: bad extension value type")
|
||||||
}
|
}
|
||||||
|
|
||||||
pb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
|
if epb, doki := pb.(extensionsMap); doki {
|
||||||
|
epb.ExtensionMap()[extension.Field] = Extension{desc: extension, value: value}
|
||||||
|
} else if epb, doki := pb.(extensionsBytes); doki {
|
||||||
|
ClearExtension(pb, extension)
|
||||||
|
ext := epb.GetExtensions()
|
||||||
|
et := reflect.TypeOf(extension.ExtensionType)
|
||||||
|
props := extensionProperties(extension)
|
||||||
|
p := NewBuffer(nil)
|
||||||
|
x := reflect.New(et)
|
||||||
|
x.Elem().Set(reflect.ValueOf(value))
|
||||||
|
if err := props.enc(p, props, toStructPointer(x)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*ext = append(*ext, p.buf...)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetBoolExtension(pb extendableProto, extension *ExtensionDesc, ifnotset bool) bool {
|
func GetBoolExtension(pb extendableProto, extension *ExtensionDesc, ifnotset bool) bool {
|
||||||
@ -58,6 +59,48 @@ func SizeOfExtensionMap(m map[int32]Extension) (n int) {
|
|||||||
return sizeExtensionMap(m)
|
return sizeExtensionMap(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sortableMapElem struct {
|
||||||
|
field int32
|
||||||
|
ext Extension
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSortableExtensionsFromMap(m map[int32]Extension) sortableExtensions {
|
||||||
|
s := make(sortableExtensions, 0, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
s = append(s, &sortableMapElem{field: k, ext: v})
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortableExtensions []*sortableMapElem
|
||||||
|
|
||||||
|
func (this sortableExtensions) Len() int { return len(this) }
|
||||||
|
|
||||||
|
func (this sortableExtensions) Swap(i, j int) { this[i], this[j] = this[j], this[i] }
|
||||||
|
|
||||||
|
func (this sortableExtensions) Less(i, j int) bool { return this[i].field < this[j].field }
|
||||||
|
|
||||||
|
func (this sortableExtensions) String() string {
|
||||||
|
sort.Sort(this)
|
||||||
|
ss := make([]string, len(this))
|
||||||
|
for i := range this {
|
||||||
|
ss[i] = fmt.Sprintf("%d: %v", this[i].field, this[i].ext)
|
||||||
|
}
|
||||||
|
return "map[" + strings.Join(ss, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringFromExtensionsMap(m map[int32]Extension) string {
|
||||||
|
return newSortableExtensionsFromMap(m).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringFromExtensionsBytes(ext []byte) string {
|
||||||
|
m, err := BytesToExtensionsMap(ext)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return StringFromExtensionsMap(m)
|
||||||
|
}
|
||||||
|
|
||||||
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
|
func EncodeExtensionMap(m map[int32]Extension, data []byte) (n int, err error) {
|
||||||
if err := encodeExtensionMap(m); err != nil {
|
if err := encodeExtensionMap(m); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
@ -83,6 +126,58 @@ func GetRawExtension(m map[int32]Extension, id int32) ([]byte, error) {
|
|||||||
return m[id].enc, nil
|
return m[id].enc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func size(buf []byte, wire int) (int, error) {
|
||||||
|
switch wire {
|
||||||
|
case WireVarint:
|
||||||
|
_, n := DecodeVarint(buf)
|
||||||
|
return n, nil
|
||||||
|
case WireFixed64:
|
||||||
|
return 8, nil
|
||||||
|
case WireBytes:
|
||||||
|
v, n := DecodeVarint(buf)
|
||||||
|
return int(v) + n, nil
|
||||||
|
case WireFixed32:
|
||||||
|
return 4, nil
|
||||||
|
case WireStartGroup:
|
||||||
|
offset := 0
|
||||||
|
for {
|
||||||
|
u, n := DecodeVarint(buf[offset:])
|
||||||
|
fwire := int(u & 0x7)
|
||||||
|
offset += n
|
||||||
|
if fwire == WireEndGroup {
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
s, err := size(buf[offset:], wire)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
offset += s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("proto: can't get size for unknown wire type %d", wire)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BytesToExtensionsMap(buf []byte) (map[int32]Extension, error) {
|
||||||
|
m := make(map[int32]Extension)
|
||||||
|
i := 0
|
||||||
|
for i < len(buf) {
|
||||||
|
tag, n := DecodeVarint(buf[i:])
|
||||||
|
if n <= 0 {
|
||||||
|
return nil, fmt.Errorf("unable to decode varint")
|
||||||
|
}
|
||||||
|
fieldNum := int32(tag >> 3)
|
||||||
|
wireType := int(tag & 0x7)
|
||||||
|
l, err := size(buf[i+n:], wireType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
end := i + int(l) + n
|
||||||
|
m[int32(fieldNum)] = Extension{enc: buf[i:end]}
|
||||||
|
i = end
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewExtension(e []byte) Extension {
|
func NewExtension(e []byte) Extension {
|
||||||
ee := Extension{enc: make([]byte, len(e))}
|
ee := Extension{enc: make([]byte, len(e))}
|
||||||
copy(ee.enc, e)
|
copy(ee.enc, e)
|
||||||
|
@ -242,8 +242,6 @@ func GetStats() Stats { return stats }
|
|||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
buf []byte // encode/decode byte stream
|
buf []byte // encode/decode byte stream
|
||||||
index int // write point
|
index int // write point
|
||||||
freelist [10][]byte // list of available buffers
|
|
||||||
nfreelist int // number of free buffers
|
|
||||||
|
|
||||||
// pools of basic types to amortize allocation.
|
// pools of basic types to amortize allocation.
|
||||||
bools []bool
|
bools []bool
|
||||||
@ -260,20 +258,11 @@ type Buffer struct {
|
|||||||
// NewBuffer allocates a new Buffer and initializes its internal data to
|
// NewBuffer allocates a new Buffer and initializes its internal data to
|
||||||
// the contents of the argument slice.
|
// the contents of the argument slice.
|
||||||
func NewBuffer(e []byte) *Buffer {
|
func NewBuffer(e []byte) *Buffer {
|
||||||
p := new(Buffer)
|
return &Buffer{buf: e}
|
||||||
if e == nil {
|
|
||||||
e = p.bufalloc()
|
|
||||||
}
|
|
||||||
p.buf = e
|
|
||||||
p.index = 0
|
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
|
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
|
||||||
func (p *Buffer) Reset() {
|
func (p *Buffer) Reset() {
|
||||||
if p.buf == nil {
|
|
||||||
p.buf = p.bufalloc()
|
|
||||||
}
|
|
||||||
p.buf = p.buf[0:0] // for reading/writing
|
p.buf = p.buf[0:0] // for reading/writing
|
||||||
p.index = 0 // for reading
|
p.index = 0 // for reading
|
||||||
}
|
}
|
||||||
@ -288,44 +277,6 @@ func (p *Buffer) SetBuf(s []byte) {
|
|||||||
// Bytes returns the contents of the Buffer.
|
// Bytes returns the contents of the Buffer.
|
||||||
func (p *Buffer) Bytes() []byte { return p.buf }
|
func (p *Buffer) Bytes() []byte { return p.buf }
|
||||||
|
|
||||||
// Allocate a buffer for the Buffer.
|
|
||||||
func (p *Buffer) bufalloc() []byte {
|
|
||||||
if p.nfreelist > 0 {
|
|
||||||
// reuse an old one
|
|
||||||
p.nfreelist--
|
|
||||||
s := p.freelist[p.nfreelist]
|
|
||||||
return s[0:0]
|
|
||||||
}
|
|
||||||
// make a new one
|
|
||||||
s := make([]byte, 0, 16)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free (and remember in freelist) a byte buffer for the Buffer.
|
|
||||||
func (p *Buffer) buffree(s []byte) {
|
|
||||||
if p.nfreelist < len(p.freelist) {
|
|
||||||
// Take next slot.
|
|
||||||
p.freelist[p.nfreelist] = s
|
|
||||||
p.nfreelist++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the smallest.
|
|
||||||
besti := -1
|
|
||||||
bestl := len(s)
|
|
||||||
for i, b := range p.freelist {
|
|
||||||
if len(b) < bestl {
|
|
||||||
besti = i
|
|
||||||
bestl = len(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overwrite the smallest.
|
|
||||||
if besti >= 0 {
|
|
||||||
p.freelist[besti] = s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
* Helper routines for simplifying the creation of optional fields of basic type.
|
||||||
*/
|
*/
|
||||||
|
@ -51,10 +51,17 @@ func structPointer_InterfaceRef(p structPointer, f field, t reflect.Type) interf
|
|||||||
}
|
}
|
||||||
|
|
||||||
func copyUintPtr(oldptr, newptr uintptr, size int) {
|
func copyUintPtr(oldptr, newptr uintptr, size int) {
|
||||||
for j := 0; j < size; j++ {
|
oldbytes := make([]byte, 0)
|
||||||
oldb := (*byte)(unsafe.Pointer(oldptr + uintptr(j)))
|
oldslice := (*reflect.SliceHeader)(unsafe.Pointer(&oldbytes))
|
||||||
*(*byte)(unsafe.Pointer(newptr + uintptr(j))) = *oldb
|
oldslice.Data = oldptr
|
||||||
}
|
oldslice.Len = size
|
||||||
|
oldslice.Cap = size
|
||||||
|
newbytes := make([]byte, 0)
|
||||||
|
newslice := (*reflect.SliceHeader)(unsafe.Pointer(&newbytes))
|
||||||
|
newslice.Data = newptr
|
||||||
|
newslice.Len = size
|
||||||
|
newslice.Cap = size
|
||||||
|
copy(newbytes, oldbytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
|
func structPointer_Copy(oldptr structPointer, newptr structPointer, size int) {
|
||||||
|
@ -575,10 +575,16 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||||||
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
|
||||||
|
|
||||||
if f.Name == "XXX_extensions" { // special case
|
if f.Name == "XXX_extensions" { // special case
|
||||||
|
if len(f.Tag.Get("protobuf")) > 0 {
|
||||||
|
p.enc = (*Buffer).enc_ext_slice_byte
|
||||||
|
p.dec = nil // not needed
|
||||||
|
p.size = size_ext_slice_byte
|
||||||
|
} else {
|
||||||
p.enc = (*Buffer).enc_map
|
p.enc = (*Buffer).enc_map
|
||||||
p.dec = nil // not needed
|
p.dec = nil // not needed
|
||||||
p.size = size_map
|
p.size = size_map
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if f.Name == "XXX_unrecognized" { // special case
|
if f.Name == "XXX_unrecognized" { // special case
|
||||||
prop.unrecField = toField(&f)
|
prop.unrecField = toField(&f)
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,41 @@
|
|||||||
// source: test.proto
|
// source: test.proto
|
||||||
// DO NOT EDIT!
|
// DO NOT EDIT!
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package testdata is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
test.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
GoEnum
|
||||||
|
GoTestField
|
||||||
|
GoTest
|
||||||
|
GoSkipTest
|
||||||
|
NonPackedTest
|
||||||
|
PackedTest
|
||||||
|
MaxTag
|
||||||
|
OldMessage
|
||||||
|
NewMessage
|
||||||
|
InnerMessage
|
||||||
|
OtherMessage
|
||||||
|
MyMessage
|
||||||
|
Ext
|
||||||
|
MyMessageSet
|
||||||
|
Empty
|
||||||
|
MessageList
|
||||||
|
Strings
|
||||||
|
Defaults
|
||||||
|
SubDefaults
|
||||||
|
RepeatedEnum
|
||||||
|
MoreRepeated
|
||||||
|
GroupOld
|
||||||
|
GroupNew
|
||||||
|
FloatingPoint
|
||||||
|
*/
|
||||||
package testdata
|
package testdata
|
||||||
|
|
||||||
import proto "github.com/coreos/etcd/third_party/code.google.com/p/gogoprotobuf/proto"
|
import proto "github.com/coreos/etcd/third_party/github.com/coreos/etcd/third_party/code.google.com/p/gogoprotobuf/proto"
|
||||||
import json "encoding/json"
|
import json "encoding/json"
|
||||||
import math "math"
|
import math "math"
|
||||||
|
|
||||||
|
@ -79,6 +79,13 @@ type textWriter struct {
|
|||||||
w writer
|
w writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// textMarshaler is implemented by Messages that can marshal themsleves.
|
||||||
|
// It is identical to encoding.TextMarshaler, introduced in go 1.2,
|
||||||
|
// which will eventually replace it.
|
||||||
|
type textMarshaler interface {
|
||||||
|
MarshalText() (text []byte, err error)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *textWriter) WriteString(s string) (n int, err error) {
|
func (w *textWriter) WriteString(s string) (n int, err error) {
|
||||||
if !strings.Contains(s, "\n") {
|
if !strings.Contains(s, "\n") {
|
||||||
if !w.compact && w.complete {
|
if !w.compact && w.complete {
|
||||||
@ -366,7 +373,15 @@ func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.indent()
|
w.indent()
|
||||||
if err := writeStruct(w, v); err != nil {
|
if tm, ok := v.Interface().(textMarshaler); ok {
|
||||||
|
text, err := tm.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = w.Write(text); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err := writeStruct(w, v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.unindent()
|
w.unindent()
|
||||||
@ -555,7 +570,18 @@ func writeExtensions(w *textWriter, pv reflect.Value) error {
|
|||||||
// Order the extensions by ID.
|
// Order the extensions by ID.
|
||||||
// This isn't strictly necessary, but it will give us
|
// This isn't strictly necessary, but it will give us
|
||||||
// canonical output, which will also make testing easier.
|
// canonical output, which will also make testing easier.
|
||||||
m := ep.ExtensionMap()
|
var m map[int32]Extension
|
||||||
|
if em, ok := ep.(extensionsMap); ok {
|
||||||
|
m = em.ExtensionMap()
|
||||||
|
} else if em, ok := ep.(extensionsBytes); ok {
|
||||||
|
eb := em.GetExtensions()
|
||||||
|
var err error
|
||||||
|
m, err = BytesToExtensionsMap(*eb)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ids := make([]int32, 0, len(m))
|
ids := make([]int32, 0, len(m))
|
||||||
for id := range m {
|
for id := range m {
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
@ -653,6 +679,19 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
|
|||||||
compact: compact,
|
compact: compact,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tm, ok := pb.(textMarshaler); ok {
|
||||||
|
text, err := tm.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err = aw.Write(text); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if bw != nil {
|
||||||
|
return bw.Flush()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Dereference the received pointer so we don't have outer < and >.
|
// Dereference the received pointer so we don't have outer < and >.
|
||||||
v := reflect.Indirect(val)
|
v := reflect.Indirect(val)
|
||||||
if err := writeStruct(aw, v); err != nil {
|
if err := writeStruct(aw, v); err != nil {
|
||||||
@ -666,7 +705,9 @@ func marshalText(w io.Writer, pb Message, compact bool) error {
|
|||||||
|
|
||||||
// MarshalText writes a given protocol buffer in text format.
|
// MarshalText writes a given protocol buffer in text format.
|
||||||
// The only errors returned are from w.
|
// The only errors returned are from w.
|
||||||
func MarshalText(w io.Writer, pb Message) error { return marshalText(w, pb, false) }
|
func MarshalText(w io.Writer, pb Message) error {
|
||||||
|
return marshalText(w, pb, false)
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalTextString is the same as MarshalText, but returns the string directly.
|
// MarshalTextString is the same as MarshalText, but returns the string directly.
|
||||||
func MarshalTextString(pb Message) string {
|
func MarshalTextString(pb Message) string {
|
||||||
|
@ -48,6 +48,13 @@ import (
|
|||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// textUnmarshaler is implemented by Messages that can unmarshal themsleves.
|
||||||
|
// It is identical to encoding.TextUnmarshaler, introduced in go 1.2,
|
||||||
|
// which will eventually replace it.
|
||||||
|
type textUnmarshaler interface {
|
||||||
|
UnmarshalText(text []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
type ParseError struct {
|
type ParseError struct {
|
||||||
Message string
|
Message string
|
||||||
Line int // 1-based line number
|
Line int // 1-based line number
|
||||||
@ -686,6 +693,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) *ParseError {
|
|||||||
default:
|
default:
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
return p.errorf("expected '{' or '<', found %q", tok.value)
|
||||||
}
|
}
|
||||||
|
// TODO: Handle nested messages which implement textUnmarshaler.
|
||||||
return p.readStruct(fv, terminator)
|
return p.readStruct(fv, terminator)
|
||||||
case reflect.Uint32:
|
case reflect.Uint32:
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
||||||
@ -704,6 +712,10 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) *ParseError {
|
|||||||
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
|
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
|
||||||
// before starting to unmarshal, so any existing data in pb is always removed.
|
// before starting to unmarshal, so any existing data in pb is always removed.
|
||||||
func UnmarshalText(s string, pb Message) error {
|
func UnmarshalText(s string, pb Message) error {
|
||||||
|
if um, ok := pb.(textUnmarshaler); ok {
|
||||||
|
err := um.UnmarshalText([]byte(s))
|
||||||
|
return err
|
||||||
|
}
|
||||||
pb.Reset()
|
pb.Reset()
|
||||||
v := reflect.ValueOf(pb)
|
v := reflect.ValueOf(pb)
|
||||||
if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
|
if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
|
||||||
|
@ -413,6 +413,16 @@ func TestUnmarshalText(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalTextCustomMessage(t *testing.T) {
|
||||||
|
msg := &textMessage{}
|
||||||
|
if err := UnmarshalText("custom", msg); err != nil {
|
||||||
|
t.Errorf("Unexpected error from custom unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
if UnmarshalText("not custom", msg) == nil {
|
||||||
|
t.Errorf("Didn't get expected error from custom unmarshal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Regression test; this caused a panic.
|
// Regression test; this caused a panic.
|
||||||
func TestRepeatedEnum(t *testing.T) {
|
func TestRepeatedEnum(t *testing.T) {
|
||||||
pb := new(RepeatedEnum)
|
pb := new(RepeatedEnum)
|
||||||
|
@ -44,6 +44,26 @@ import (
|
|||||||
pb "./testdata"
|
pb "./testdata"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// textMessage implements the methods that allow it to marshal and unmarshal
|
||||||
|
// itself as text.
|
||||||
|
type textMessage struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*textMessage) MarshalText() ([]byte, error) {
|
||||||
|
return []byte("custom"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*textMessage) UnmarshalText(bytes []byte) error {
|
||||||
|
if string(bytes) != "custom" {
|
||||||
|
return errors.New("expected 'custom'")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*textMessage) Reset() {}
|
||||||
|
func (*textMessage) String() string { return "" }
|
||||||
|
func (*textMessage) ProtoMessage() {}
|
||||||
|
|
||||||
func newTestMessage() *pb.MyMessage {
|
func newTestMessage() *pb.MyMessage {
|
||||||
msg := &pb.MyMessage{
|
msg := &pb.MyMessage{
|
||||||
Count: proto.Int32(42),
|
Count: proto.Int32(42),
|
||||||
@ -153,6 +173,16 @@ func TestMarshalText(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalTextCustomMessage(t *testing.T) {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if err := proto.MarshalText(buf, &textMessage{}); err != nil {
|
||||||
|
t.Fatalf("proto.MarshalText: %v", err)
|
||||||
|
}
|
||||||
|
s := buf.String()
|
||||||
|
if s != "custom" {
|
||||||
|
t.Errorf("Got %q, expected %q", s, "custom")
|
||||||
|
}
|
||||||
|
}
|
||||||
func TestMarshalTextNil(t *testing.T) {
|
func TestMarshalTextNil(t *testing.T) {
|
||||||
want := "<nil>"
|
want := "<nil>"
|
||||||
tests := []proto.Message{nil, (*pb.MyMessage)(nil)}
|
tests := []proto.Message{nil, (*pb.MyMessage)(nil)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user