|
@@ -60,9 +60,9 @@ func (e *RequiredNotSetError) Error() string {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
|
- // ErrRepeatedHasNil is the error returned if Marshal is called with
|
|
|
|
|
|
|
+ // errRepeatedHasNil is the error returned if Marshal is called with
|
|
|
// a struct with a repeated field containing a nil element.
|
|
// a struct with a repeated field containing a nil element.
|
|
|
- ErrRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
|
|
|
|
|
|
+ errRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
|
|
|
|
|
|
|
// ErrNil is the error returned if Marshal is called with nil.
|
|
// ErrNil is the error returned if Marshal is called with nil.
|
|
|
ErrNil = errors.New("proto: Marshal called with nil")
|
|
ErrNil = errors.New("proto: Marshal called with nil")
|
|
@@ -298,6 +298,16 @@ func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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 {
|
|
func size_bool(p *Properties, base structPointer) int {
|
|
|
v := *structPointer_Bool(base, p.field)
|
|
v := *structPointer_Bool(base, p.field)
|
|
|
if v == nil {
|
|
if v == nil {
|
|
@@ -306,6 +316,14 @@ func size_bool(p *Properties, base structPointer) int {
|
|
|
return len(p.tagcode) + 1 // each bool takes exactly one byte
|
|
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.
|
|
// Encode an int32.
|
|
|
func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
|
|
func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
|
|
|
v := structPointer_Word32(base, p.field)
|
|
v := structPointer_Word32(base, p.field)
|
|
@@ -318,6 +336,17 @@ func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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) {
|
|
func size_int32(p *Properties, base structPointer) (n int) {
|
|
|
v := structPointer_Word32(base, p.field)
|
|
v := structPointer_Word32(base, p.field)
|
|
|
if word32_IsNil(v) {
|
|
if word32_IsNil(v) {
|
|
@@ -329,6 +358,17 @@ func size_int32(p *Properties, base structPointer) (n int) {
|
|
|
return
|
|
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.
|
|
// Encode a uint32.
|
|
|
// Exactly the same as int32, except for no sign extension.
|
|
// Exactly the same as int32, except for no sign extension.
|
|
|
func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
|
|
func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
|
|
@@ -342,6 +382,17 @@ func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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) {
|
|
func size_uint32(p *Properties, base structPointer) (n int) {
|
|
|
v := structPointer_Word32(base, p.field)
|
|
v := structPointer_Word32(base, p.field)
|
|
|
if word32_IsNil(v) {
|
|
if word32_IsNil(v) {
|
|
@@ -353,6 +404,17 @@ func size_uint32(p *Properties, base structPointer) (n int) {
|
|
|
return
|
|
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.
|
|
// Encode an int64.
|
|
|
func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
|
|
func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
|
|
|
v := structPointer_Word64(base, p.field)
|
|
v := structPointer_Word64(base, p.field)
|
|
@@ -365,6 +427,17 @@ func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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) {
|
|
func size_int64(p *Properties, base structPointer) (n int) {
|
|
|
v := structPointer_Word64(base, p.field)
|
|
v := structPointer_Word64(base, p.field)
|
|
|
if word64_IsNil(v) {
|
|
if word64_IsNil(v) {
|
|
@@ -376,6 +449,17 @@ func size_int64(p *Properties, base structPointer) (n int) {
|
|
|
return
|
|
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.
|
|
// Encode a string.
|
|
|
func (o *Buffer) enc_string(p *Properties, base structPointer) error {
|
|
func (o *Buffer) enc_string(p *Properties, base structPointer) error {
|
|
|
v := *structPointer_String(base, p.field)
|
|
v := *structPointer_String(base, p.field)
|
|
@@ -388,6 +472,16 @@ func (o *Buffer) enc_string(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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) {
|
|
func size_string(p *Properties, base structPointer) (n int) {
|
|
|
v := *structPointer_String(base, p.field)
|
|
v := *structPointer_String(base, p.field)
|
|
|
if v == nil {
|
|
if v == nil {
|
|
@@ -399,6 +493,16 @@ func size_string(p *Properties, base structPointer) (n int) {
|
|
|
return
|
|
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.
|
|
// All protocol buffer fields are nillable, but be careful.
|
|
|
func isNil(v reflect.Value) bool {
|
|
func isNil(v reflect.Value) bool {
|
|
|
switch v.Kind() {
|
|
switch v.Kind() {
|
|
@@ -551,6 +655,16 @@ func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
|
|
|
return nil
|
|
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) {
|
|
func size_slice_byte(p *Properties, base structPointer) (n int) {
|
|
|
s := *structPointer_Bytes(base, p.field)
|
|
s := *structPointer_Bytes(base, p.field)
|
|
|
if s == nil {
|
|
if s == nil {
|
|
@@ -561,6 +675,16 @@ func size_slice_byte(p *Properties, base structPointer) (n int) {
|
|
|
return
|
|
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).
|
|
// Encode a slice of int32s ([]int32).
|
|
|
func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
|
|
func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
|
|
|
s := structPointer_Word32Slice(base, p.field)
|
|
s := structPointer_Word32Slice(base, p.field)
|
|
@@ -815,7 +939,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
|
|
|
for i := 0; i < l; i++ {
|
|
for i := 0; i < l; i++ {
|
|
|
structp := s.Index(i)
|
|
structp := s.Index(i)
|
|
|
if structPointer_IsNil(structp) {
|
|
if structPointer_IsNil(structp) {
|
|
|
- return ErrRepeatedHasNil
|
|
|
|
|
|
|
+ return errRepeatedHasNil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Can the object marshal itself?
|
|
// Can the object marshal itself?
|
|
@@ -834,7 +958,7 @@ func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) err
|
|
|
err := o.enc_len_struct(p.sprop, structp, &state)
|
|
err := o.enc_len_struct(p.sprop, structp, &state)
|
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
|
if err == ErrNil {
|
|
if err == ErrNil {
|
|
|
- return ErrRepeatedHasNil
|
|
|
|
|
|
|
+ return errRepeatedHasNil
|
|
|
}
|
|
}
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
@@ -877,7 +1001,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
|
|
|
for i := 0; i < l; i++ {
|
|
for i := 0; i < l; i++ {
|
|
|
b := s.Index(i)
|
|
b := s.Index(i)
|
|
|
if structPointer_IsNil(b) {
|
|
if structPointer_IsNil(b) {
|
|
|
- return ErrRepeatedHasNil
|
|
|
|
|
|
|
+ return errRepeatedHasNil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
|
|
o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
|
|
@@ -886,7 +1010,7 @@ func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error
|
|
|
|
|
|
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
|
if err == ErrNil {
|
|
if err == ErrNil {
|
|
|
- return ErrRepeatedHasNil
|
|
|
|
|
|
|
+ return errRepeatedHasNil
|
|
|
}
|
|
}
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
@@ -945,6 +1069,108 @@ func size_map(p *Properties, base structPointer) int {
|
|
|
return sizeExtensionMap(v)
|
|
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 for key and val are the responsibility of the sub-sizer.
|
|
|
|
|
+ keysize := p.mkeyprop.size(p.mkeyprop, keybase)
|
|
|
|
|
+ valsize := p.mvalprop.size(p.mvalprop, valbase)
|
|
|
|
|
+ entry := keysize + valsize
|
|
|
|
|
+ // Add on tag code and length of map entry itself.
|
|
|
|
|
+ n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
|
|
|
|
|
+ }
|
|
|
|
|
+ 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.
|
|
// Encode a struct.
|
|
|
func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
|
func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
|
|
var state errorState
|
|
var state errorState
|
|
@@ -960,6 +1186,9 @@ func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
|
|
|
if p.Required && state.err == nil {
|
|
if p.Required && state.err == nil {
|
|
|
state.err = &RequiredNotSetError{p.Name}
|
|
state.err = &RequiredNotSetError{p.Name}
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if err == errRepeatedHasNil {
|
|
|
|
|
+ // Give more context to nil values in repeated fields.
|
|
|
|
|
+ return errors.New("repeated field " + p.OrigName + " has nil element")
|
|
|
} else if !state.shouldContinue(err, p) {
|
|
} else if !state.shouldContinue(err, p) {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|
|
@@ -999,10 +1228,15 @@ var zeroes [20]byte // longer than any conceivable sizeVarint
|
|
|
|
|
|
|
|
// Encode a struct, preceded by its encoded length (as a varint).
|
|
// Encode a struct, preceded by its encoded length (as a varint).
|
|
|
func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
|
|
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)
|
|
iLen := len(o.buf)
|
|
|
o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
|
|
o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
|
|
|
iMsg := len(o.buf)
|
|
iMsg := len(o.buf)
|
|
|
- err := o.enc_struct(prop, base)
|
|
|
|
|
|
|
+ err := enc()
|
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
if err != nil && !state.shouldContinue(err, nil) {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|