internal/impl: add fast-path unmarshal

Benchmarks run with:
  go test ./benchmarks/ -bench=Wire  -benchtime=500ms -benchmem -count=8

Fast-path vs. parent commit:

  name                                      old time/op    new time/op    delta
  Wire/Unmarshal/google_message1_proto2-12    1.35µs ± 2%    0.45µs ± 4%  -67.01%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message1_proto3-12    1.07µs ± 1%    0.31µs ± 1%  -71.04%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message2-12            691µs ± 2%     188µs ± 2%  -72.78%  (p=0.000 n=7+8)

  name                                      old allocs/op  new allocs/op  delta
  Wire/Unmarshal/google_message1_proto2-12      60.0 ± 0%      25.0 ± 0%  -58.33%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message1_proto3-12      42.0 ± 0%       7.0 ± 0%  -83.33%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message2-12            28.6k ± 0%      8.5k ± 0%  -70.34%  (p=0.000 n=8+8)

Fast-path vs. -v1:

  name                                      old time/op    new time/op    delta
  Wire/Unmarshal/google_message1_proto2-12     702ns ± 1%     445ns ± 4%   -36.58%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message1_proto3-12     604ns ± 1%     311ns ± 1%   -48.54%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message2-12            179µs ± 3%     188µs ± 2%    +5.30%  (p=0.000 n=7+8)

  name                                      old allocs/op  new allocs/op  delta
  Wire/Unmarshal/google_message1_proto2-12      26.0 ± 0%      25.0 ± 0%    -3.85%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message1_proto3-12      8.00 ± 0%      7.00 ± 0%   -12.50%  (p=0.000 n=8+8)
  Wire/Unmarshal/google_message2-12            8.49k ± 0%     8.49k ± 0%    -0.01%  (p=0.000 n=8+8)

Change-Id: I6247ac3fd66a63d9acb902cbd192094ee3d151c3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/185147
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/cmd/generate-types/impl.go b/internal/cmd/generate-types/impl.go
index 6909994..a2e2aa9 100644
--- a/internal/cmd/generate-types/impl.go
+++ b/internal/cmd/generate-types/impl.go
@@ -50,6 +50,14 @@
 {{- end -}}
 {{- end -}}
 
+{{- define "Consume" -}}
+{{- if eq .Name "String" -}}
+wire.ConsumeString(b)
+{{- else -}}
+wire.Consume{{.WireType}}(b)
+{{- end -}}
+{{- end -}}
+
 {{- range .}}
 {{- if .FromGoType }}
 // size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
@@ -68,9 +76,23 @@
 	return b, nil
 }
 
+// consume{{.Name}} wire decodes a {{.GoType}} pointer as a {{.Name}}.
+func consume{{.Name}}(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != {{.WireType.Expr}} {
+		return 0, errUnknown
+	}
+	v, n := {{template "Consume" .}}
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.{{.GoType.PointerMethod}}() = {{.ToGoType}}
+	return n, nil
+}
+
 var coder{{.Name}} = pointerCoderFuncs{
-	size:    size{{.Name}},
-	marshal: append{{.Name}},
+	size:      size{{.Name}},
+	marshal:   append{{.Name}},
+	unmarshal: consume{{.Name}},
 }
 
 // size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
@@ -96,8 +118,9 @@
 }
 
 var coder{{.Name}}NoZero = pointerCoderFuncs{
-	size:    size{{.Name}}NoZero,
-	marshal: append{{.Name}}NoZero,
+	size:      size{{.Name}}NoZero,
+	marshal:   append{{.Name}}NoZero,
+	unmarshal: consume{{.Name}},
 }
 
 {{- if not .NoPointer}}
@@ -110,7 +133,7 @@
 	return tagsize + {{template "Size" .}}
 }
 
-// append{{.Name}} wire encodes a *{{.GoType}} pointer as a {{.Name}}.
+// append{{.Name}}Ptr wire encodes a *{{.GoType}} pointer as a {{.Name}}.
 // It panics if the pointer is nil.
 func append{{.Name}}Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.{{.GoType.PointerMethod}}Ptr()
@@ -119,9 +142,27 @@
 	return b, nil
 }
 
+// consume{{.Name}}Ptr wire decodes a *{{.GoType}} pointer as a {{.Name}}.
+func consume{{.Name}}Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != {{.WireType.Expr}} {
+		return 0, errUnknown
+	}
+	v, n := {{template "Consume" .}}
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.{{.GoType.PointerMethod}}Ptr()
+	if *vp == nil {
+		*vp = new({{.GoType}})
+	}
+	**vp = {{.ToGoType}}
+	return n, nil
+}
+
 var coder{{.Name}}Ptr = pointerCoderFuncs{
-	size:    size{{.Name}}Ptr,
-	marshal: append{{.Name}}Ptr,
+	size:      size{{.Name}}Ptr,
+	marshal:   append{{.Name}}Ptr,
+	unmarshal: consume{{.Name}}Ptr,
 }
 {{end}}
 
@@ -148,9 +189,43 @@
 	return b, nil
 }
 
+// consume{{.Name}}Slice wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
+func consume{{.Name}}Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.{{.GoType.PointerMethod}}Slice()
+	{{- if .WireType.Packable}}
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := {{template "Consume" .}}
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, {{.ToGoType}})
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	{{- end}}
+	if wtyp != {{.WireType.Expr}} {
+		return 0, errUnknown
+	}
+	v, n := {{template "Consume" .}}
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, {{.ToGoType}})
+	return n, nil
+}
+
 var coder{{.Name}}Slice = pointerCoderFuncs{
-	size:    size{{.Name}}Slice,
-	marshal: append{{.Name}}Slice,
+	size:      size{{.Name}}Slice,
+	marshal:   append{{.Name}}Slice,
+	unmarshal: consume{{.Name}}Slice,
 }
 
 {{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
@@ -194,8 +269,9 @@
 }
 
 var coder{{.Name}}PackedSlice = pointerCoderFuncs{
-	size:    size{{.Name}}PackedSlice,
-	marshal: append{{.Name}}PackedSlice,
+	size:      size{{.Name}}PackedSlice,
+	marshal:   append{{.Name}}PackedSlice,
+	unmarshal: consume{{.Name}}Slice,
 }
 {{end}}
 
@@ -215,9 +291,22 @@
 	return b, nil
 }
 
+// consume{{.Name}}Iface decodes a {{.GoType}} value as a {{.Name}}.
+func consume{{.Name}}Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != {{.WireType.Expr}} {
+		return nil, 0, errUnknown
+	}
+	v, n := {{template "Consume" .}}
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return {{.ToGoType}}, n, nil
+}
+
 var coder{{.Name}}Iface = ifaceCoderFuncs{
 	size:    size{{.Name}}Iface,
 	marshal: append{{.Name}}Iface,
+	unmarshal: consume{{.Name}}Iface,
 }
 
 // size{{.Name}}SliceIface returns the size of wire encoding a []{{.GoType}} value as a repeated {{.Name}}.
@@ -243,9 +332,44 @@
 	return b, nil
 }
 
+// consume{{.Name}}SliceIface wire decodes a []{{.GoType}} value as a repeated {{.Name}}.
+func consume{{.Name}}SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]{{.GoType}})
+	{{- if .WireType.Packable}}
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := {{template "Consume" .}}
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, {{.ToGoType}})
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	{{- end}}
+	if wtyp != {{.WireType.Expr}} {
+		return nil, 0, errUnknown
+	}
+	v, n := {{template "Consume" .}}
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, {{.ToGoType}})
+	return ival, n, nil
+}
+
+
 var coder{{.Name}}SliceIface = ifaceCoderFuncs{
-	size:    size{{.Name}}SliceIface,
-	marshal: append{{.Name}}SliceIface,
+	size:      size{{.Name}}SliceIface,
+	marshal:   append{{.Name}}SliceIface,
+	unmarshal: consume{{.Name}}SliceIface,
 }
 
 {{end -}}
diff --git a/internal/cmd/generate-types/proto.go b/internal/cmd/generate-types/proto.go
index db20f0b..e507b03 100644
--- a/internal/cmd/generate-types/proto.go
+++ b/internal/cmd/generate-types/proto.go
@@ -86,6 +86,7 @@
 
 	// Conversions to/from generated structures.
 	GoType     GoType
+	ToGoType   Expr
 	FromGoType Expr
 	NoPointer  bool
 }
@@ -101,6 +102,7 @@
 		ToValue:    "wire.DecodeBool(v)",
 		FromValue:  "wire.EncodeBool(v.Bool())",
 		GoType:     GoBool,
+		ToGoType:   "wire.DecodeBool(v)",
 		FromGoType: "wire.EncodeBool(v)",
 	},
 	{
@@ -115,6 +117,7 @@
 		ToValue:    "int32(v)",
 		FromValue:  "uint64(int32(v.Int()))",
 		GoType:     GoInt32,
+		ToGoType:   "int32(v)",
 		FromGoType: "uint64(v)",
 	},
 	{
@@ -123,6 +126,7 @@
 		ToValue:    "int32(wire.DecodeZigZag(v & math.MaxUint32))",
 		FromValue:  "wire.EncodeZigZag(int64(int32(v.Int())))",
 		GoType:     GoInt32,
+		ToGoType:   "int32(wire.DecodeZigZag(v & math.MaxUint32))",
 		FromGoType: "wire.EncodeZigZag(int64(v))",
 	},
 	{
@@ -131,6 +135,7 @@
 		ToValue:    "uint32(v)",
 		FromValue:  "uint64(uint32(v.Uint()))",
 		GoType:     GoUint32,
+		ToGoType:   "uint32(v)",
 		FromGoType: "uint64(v)",
 	},
 	{
@@ -139,6 +144,7 @@
 		ToValue:    "int64(v)",
 		FromValue:  "uint64(v.Int())",
 		GoType:     GoInt64,
+		ToGoType:   "int64(v)",
 		FromGoType: "uint64(v)",
 	},
 	{
@@ -147,6 +153,7 @@
 		ToValue:    "wire.DecodeZigZag(v)",
 		FromValue:  "wire.EncodeZigZag(v.Int())",
 		GoType:     GoInt64,
+		ToGoType:   "wire.DecodeZigZag(v)",
 		FromGoType: "wire.EncodeZigZag(v)",
 	},
 	{
@@ -155,6 +162,7 @@
 		ToValue:    "v",
 		FromValue:  "v.Uint()",
 		GoType:     GoUint64,
+		ToGoType:   "v",
 		FromGoType: "v",
 	},
 	{
@@ -163,6 +171,7 @@
 		ToValue:    "int32(v)",
 		FromValue:  "uint32(v.Int())",
 		GoType:     GoInt32,
+		ToGoType:   "int32(v)",
 		FromGoType: "uint32(v)",
 	},
 	{
@@ -171,6 +180,7 @@
 		ToValue:    "uint32(v)",
 		FromValue:  "uint32(v.Uint())",
 		GoType:     GoUint32,
+		ToGoType:   "v",
 		FromGoType: "v",
 	},
 	{
@@ -179,6 +189,7 @@
 		ToValue:    "math.Float32frombits(uint32(v))",
 		FromValue:  "math.Float32bits(float32(v.Float()))",
 		GoType:     GoFloat32,
+		ToGoType:   "math.Float32frombits(v)",
 		FromGoType: "math.Float32bits(v)",
 	},
 	{
@@ -187,6 +198,7 @@
 		ToValue:    "int64(v)",
 		FromValue:  "uint64(v.Int())",
 		GoType:     GoInt64,
+		ToGoType:   "int64(v)",
 		FromGoType: "uint64(v)",
 	},
 	{
@@ -195,6 +207,7 @@
 		ToValue:    "v",
 		FromValue:  "v.Uint()",
 		GoType:     GoUint64,
+		ToGoType:   "v",
 		FromGoType: "v",
 	},
 	{
@@ -203,6 +216,7 @@
 		ToValue:    "math.Float64frombits(v)",
 		FromValue:  "math.Float64bits(v.Float())",
 		GoType:     GoFloat64,
+		ToGoType:   "math.Float64frombits(v)",
 		FromGoType: "math.Float64bits(v)",
 	},
 	{
@@ -211,6 +225,7 @@
 		ToValue:    "string(v)",
 		FromValue:  "v.String()",
 		GoType:     GoString,
+		ToGoType:   "v",
 		FromGoType: "v",
 	},
 	{
@@ -219,6 +234,7 @@
 		ToValue:    "append(([]byte)(nil), v...)",
 		FromValue:  "v.Bytes()",
 		GoType:     GoBytes,
+		ToGoType:   "append(([]byte)(nil), v...)",
 		FromGoType: "v",
 		NoPointer:  true,
 	},
diff --git a/internal/encoding/wire/wire.go b/internal/encoding/wire/wire.go
index e66123a..224ddf7 100644
--- a/internal/encoding/wire/wire.go
+++ b/internal/encoding/wire/wire.go
@@ -425,11 +425,6 @@
 	return append(AppendVarint(b, uint64(len(v))), v...)
 }
 
-// AppendString appends v to b as a length-prefixed bytes value.
-func AppendString(b []byte, v string) []byte {
-	return append(AppendVarint(b, uint64(len(v))), v...)
-}
-
 // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
 // This returns a negative length upon an error (see ParseError).
 func ConsumeBytes(b []byte) (v []byte, n int) {
@@ -449,6 +444,18 @@
 	return SizeVarint(uint64(n)) + n
 }
 
+// AppendString appends v to b as a length-prefixed bytes value.
+func AppendString(b []byte, v string) []byte {
+	return append(AppendVarint(b, uint64(len(v))), v...)
+}
+
+// ConsumeString parses b as a length-prefixed bytes value, reporting its length.
+// This returns a negative length upon an error (see ParseError).
+func ConsumeString(b []byte) (v string, n int) {
+	bb, n := ConsumeBytes(b)
+	return string(bb), n
+}
+
 // AppendGroup appends v to b as group value, with a trailing end group marker.
 // The value v must not contain the end marker.
 func AppendGroup(b []byte, num Number, v []byte) []byte {
diff --git a/internal/impl/codec_extension.go b/internal/impl/codec_extension.go
index 577f1df..10a9fa2 100644
--- a/internal/impl/codec_extension.go
+++ b/internal/impl/codec_extension.go
@@ -13,9 +13,10 @@
 )
 
 type extensionFieldInfo struct {
-	wiretag uint64
-	tagsize int
-	funcs   ifaceCoderFuncs
+	wiretag             uint64
+	tagsize             int
+	unmarshalNeedsValue bool
+	funcs               ifaceCoderFuncs
 }
 
 func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
@@ -34,7 +35,17 @@
 		tagsize: wire.SizeVarint(wiretag),
 		funcs:   encoderFuncsForValue(xt, xt.GoType()),
 	}
-
+	// Does the unmarshal function need a value passed to it?
+	// This is true for composite types, where we pass in a message, list, or map to fill in,
+	// and for enums, where we pass in a prototype value to specify the concrete enum type.
+	switch xt.Kind() {
+	case pref.MessageKind, pref.GroupKind, pref.EnumKind:
+		e.unmarshalNeedsValue = true
+	default:
+		if xt.Cardinality() == pref.Repeated {
+			e.unmarshalNeedsValue = true
+		}
+	}
 	mi.extensionFieldInfosMu.Lock()
 	if mi.extensionFieldInfos == nil {
 		mi.extensionFieldInfos = make(map[pref.ExtensionType]*extensionFieldInfo)
diff --git a/internal/impl/codec_field.go b/internal/impl/codec_field.go
index 15124c0..09389b0 100644
--- a/internal/impl/codec_field.go
+++ b/internal/impl/codec_field.go
@@ -5,7 +5,6 @@
 package impl
 
 import (
-	"fmt"
 	"reflect"
 	"unicode/utf8"
 
@@ -19,61 +18,59 @@
 func (errInvalidUTF8) Error() string     { return "string field contains invalid UTF-8" }
 func (errInvalidUTF8) InvalidUTF8() bool { return true }
 
-func makeOneofFieldCoder(fs reflect.StructField, od pref.OneofDescriptor, structFields map[pref.FieldNumber]reflect.StructField, otypes map[pref.FieldNumber]reflect.Type) pointerCoderFuncs {
-	type oneofFieldInfo struct {
-		wiretag uint64
-		tagsize int
-		funcs   pointerCoderFuncs
-	}
-
-	oneofFieldInfos := make(map[reflect.Type]oneofFieldInfo)
-	for i, fields := 0, od.Fields(); i < fields.Len(); i++ {
-		fd := fields.Get(i)
-		ot := otypes[fd.Number()]
-		wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
-		oneofFieldInfos[ot] = oneofFieldInfo{
-			wiretag: wiretag,
-			tagsize: wire.SizeVarint(wiretag),
-			funcs:   fieldCoder(fd, ot.Field(0).Type),
-		}
-	}
+func makeOneofFieldCoder(si structInfo, fd pref.FieldDescriptor) pointerCoderFuncs {
+	ot := si.oneofWrappersByNumber[fd.Number()]
+	funcs := fieldCoder(fd, ot.Field(0).Type)
+	fs := si.oneofsByName[fd.ContainingOneof().Name()]
 	ft := fs.Type
-	getInfo := func(p pointer) (pointer, oneofFieldInfo) {
+	wiretag := wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
+	tagsize := wire.SizeVarint(wiretag)
+	getInfo := func(p pointer) (pointer, bool) {
 		v := p.AsValueOf(ft).Elem()
 		if v.IsNil() {
-			return pointer{}, oneofFieldInfo{}
+			return pointer{}, false
 		}
 		v = v.Elem() // interface -> *struct
-		telem := v.Elem().Type()
-		info, ok := oneofFieldInfos[telem]
-		if !ok {
-			panic(fmt.Errorf("invalid oneof type %v", telem))
+		if v.Elem().Type() != ot {
+			return pointer{}, false
 		}
-		return pointerOfValue(v).Apply(zeroOffset), info
+		return pointerOfValue(v).Apply(zeroOffset), true
 	}
-	return pointerCoderFuncs{
+	pcf := pointerCoderFuncs{
 		size: func(p pointer, _ int, opts marshalOptions) int {
-			v, info := getInfo(p)
-			if info.funcs.size == nil {
+			v, ok := getInfo(p)
+			if !ok {
 				return 0
 			}
-			return info.funcs.size(v, info.tagsize, opts)
+			return funcs.size(v, tagsize, opts)
 		},
 		marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
-			v, info := getInfo(p)
-			if info.funcs.marshal == nil {
+			v, ok := getInfo(p)
+			if !ok {
 				return b, nil
 			}
-			return info.funcs.marshal(b, v, info.wiretag, opts)
+			return funcs.marshal(b, v, wiretag, opts)
 		},
-		isInit: func(p pointer) error {
-			v, info := getInfo(p)
-			if info.funcs.isInit == nil {
-				return nil
+		unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+			v := reflect.New(ot)
+			n, err := funcs.unmarshal(b, pointerOfValue(v).Apply(zeroOffset), wtyp, opts)
+			if err != nil {
+				return 0, err
 			}
-			return info.funcs.isInit(v)
+			p.AsValueOf(ft).Elem().Set(v)
+			return n, nil
 		},
 	}
+	if funcs.isInit != nil {
+		pcf.isInit = func(p pointer) error {
+			v, ok := getInfo(p)
+			if !ok {
+				return nil
+			}
+			return funcs.isInit(v)
+		}
+	}
+	return pcf
 }
 
 func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
@@ -85,6 +82,9 @@
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 				return appendMessageInfo(b, p, wiretag, fi, opts)
 			},
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				return consumeMessageInfo(b, p, fi, wtyp, opts)
+			},
 			isInit: func(p pointer) error {
 				return fi.isInitializedPointer(p.Elem())
 			},
@@ -99,6 +99,13 @@
 				m := asMessage(p.AsValueOf(ft).Elem())
 				return appendMessage(b, m, wiretag, opts)
 			},
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				mp := p.AsValueOf(ft).Elem()
+				if mp.IsNil() {
+					mp.Set(reflect.New(ft.Elem()))
+				}
+				return consumeMessage(b, asMessage(mp), wtyp, opts)
+			},
 			isInit: func(p pointer) error {
 				m := asMessage(p.AsValueOf(ft).Elem())
 				return proto.IsInitialized(m)
@@ -117,6 +124,23 @@
 	return mi.marshalAppendPointer(b, p.Elem(), opts)
 }
 
+func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	if p.Elem().IsNil() {
+		p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
+	}
+	if _, err := mi.unmarshalPointer(v, p.Elem(), 0, opts); err != nil {
+		return 0, err
+	}
+	return n, nil
+}
+
 func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
 	return wire.SizeBytes(proto.Size(m)) + tagsize
 }
@@ -127,6 +151,20 @@
 	return opts.Options().MarshalAppend(b, m)
 }
 
+func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	if err := opts.Options().Unmarshal(v, m); err != nil {
+		return 0, err
+	}
+	return n, nil
+}
+
 func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
 	m := Export{}.MessageOf(ival).Interface()
 	return sizeMessage(m, tagsize, opts)
@@ -137,18 +175,26 @@
 	return appendMessage(b, m, wiretag, opts)
 }
 
+func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
+	m := Export{}.MessageOf(ival).Interface()
+	n, err := consumeMessage(b, m, wtyp, opts)
+	return ival, n, err
+}
+
 func isInitMessageIface(ival interface{}) error {
 	m := Export{}.MessageOf(ival).Interface()
 	return proto.IsInitialized(m)
 }
 
 var coderMessageIface = ifaceCoderFuncs{
-	size:    sizeMessageIface,
-	marshal: appendMessageIface,
-	isInit:  isInitMessageIface,
+	size:      sizeMessageIface,
+	marshal:   appendMessageIface,
+	unmarshal: consumeMessageIface,
+	isInit:    isInitMessageIface,
 }
 
 func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
+	num := fd.Number()
 	if fi, ok := getMessageInfo(ft); ok {
 		return pointerCoderFuncs{
 			size: func(p pointer, tagsize int, opts marshalOptions) int {
@@ -157,6 +203,9 @@
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 				return appendGroupType(b, p, wiretag, fi, opts)
 			},
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				return consumeGroupType(b, p, fi, num, wtyp, opts)
+			},
 			isInit: func(p pointer) error {
 				return fi.isInitializedPointer(p.Elem())
 			},
@@ -171,6 +220,13 @@
 				m := asMessage(p.AsValueOf(ft).Elem())
 				return appendGroup(b, m, wiretag, opts)
 			},
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				mp := p.AsValueOf(ft).Elem()
+				if mp.IsNil() {
+					mp.Set(reflect.New(ft.Elem()))
+				}
+				return consumeGroup(b, asMessage(mp), num, wtyp, opts)
+			},
 			isInit: func(p pointer) error {
 				m := asMessage(p.AsValueOf(ft).Elem())
 				return proto.IsInitialized(m)
@@ -190,6 +246,16 @@
 	return b, err
 }
 
+func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.StartGroupType {
+		return 0, errUnknown
+	}
+	if p.Elem().IsNil() {
+		p.SetPointer(pointerOfValue(reflect.New(mi.GoType.Elem())))
+	}
+	return mi.unmarshalPointer(b, p.Elem(), num, opts)
+}
+
 func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
 	return 2*tagsize + proto.Size(m)
 }
@@ -201,30 +267,47 @@
 	return b, err
 }
 
-func sizeGroupIface(ival interface{}, tagsize int, opts marshalOptions) int {
-	m := Export{}.MessageOf(ival).Interface()
-	return sizeGroup(m, tagsize, opts)
+func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.StartGroupType {
+		return 0, errUnknown
+	}
+	b, n := wire.ConsumeGroup(num, b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	return n, opts.Options().Unmarshal(b, m)
 }
 
-func appendGroupIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
-	m := Export{}.MessageOf(ival).Interface()
-	return appendGroup(b, m, wiretag, opts)
-}
-
-var coderGroupIface = ifaceCoderFuncs{
-	size:    sizeGroupIface,
-	marshal: appendGroupIface,
-	isInit:  isInitMessageIface,
+func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
+	return ifaceCoderFuncs{
+		size: func(ival interface{}, tagsize int, opts marshalOptions) int {
+			m := Export{}.MessageOf(ival).Interface()
+			return sizeGroup(m, tagsize, opts)
+		},
+		marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
+			m := Export{}.MessageOf(ival).Interface()
+			return appendGroup(b, m, wiretag, opts)
+		},
+		unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
+			m := Export{}.MessageOf(ival).Interface()
+			n, err := consumeGroup(b, m, num, wtyp, opts)
+			return ival, n, err
+		},
+		isInit: isInitMessageIface,
+	}
 }
 
 func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
 	if fi, ok := getMessageInfo(ft); ok {
 		return pointerCoderFuncs{
+			size: func(p pointer, tagsize int, opts marshalOptions) int {
+				return sizeMessageSliceInfo(p, fi, tagsize, opts)
+			},
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 				return appendMessageSliceInfo(b, p, wiretag, fi, opts)
 			},
-			size: func(p pointer, tagsize int, opts marshalOptions) int {
-				return sizeMessageSliceInfo(p, fi, tagsize, opts)
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				return consumeMessageSliceInfo(b, p, fi, wtyp, opts)
 			},
 			isInit: func(p pointer) error {
 				return isInitMessageSliceInfo(p, fi)
@@ -238,6 +321,9 @@
 		marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 			return appendMessageSlice(b, p, wiretag, ft, opts)
 		},
+		unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+			return consumeMessageSlice(b, p, ft, wtyp, opts)
+		},
 		isInit: func(p pointer) error {
 			return isInitMessageSlice(p, ft)
 		},
@@ -268,6 +354,23 @@
 	return b, nil
 }
 
+func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	m := reflect.New(mi.GoType.Elem()).Interface()
+	mp := pointerOfIface(m)
+	if _, err := mi.unmarshalPointer(v, mp, 0, opts); err != nil {
+		return 0, err
+	}
+	p.AppendPointerSlice(mp)
+	return n, nil
+}
+
 func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
 	s := p.PointerSlice()
 	for _, v := range s {
@@ -282,7 +385,7 @@
 	s := p.PointerSlice()
 	n := 0
 	for _, v := range s {
-		m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
+		m := asMessage(v.AsValueOf(goType.Elem()))
 		n += wire.SizeBytes(proto.Size(m)) + tagsize
 	}
 	return n
@@ -292,7 +395,7 @@
 	s := p.PointerSlice()
 	var err error
 	for _, v := range s {
-		m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
+		m := asMessage(v.AsValueOf(goType.Elem()))
 		b = wire.AppendVarint(b, wiretag)
 		siz := proto.Size(m)
 		b = wire.AppendVarint(b, uint64(siz))
@@ -304,10 +407,26 @@
 	return b, nil
 }
 
+func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	mp := reflect.New(goType.Elem())
+	if err := opts.Options().Unmarshal(v, asMessage(mp)); err != nil {
+		return 0, err
+	}
+	p.AppendPointerSlice(pointerOfValue(mp))
+	return n, nil
+}
+
 func isInitMessageSlice(p pointer, goType reflect.Type) error {
 	s := p.PointerSlice()
 	for _, v := range s {
-		m := Export{}.MessageOf(v.AsValueOf(goType.Elem()).Interface()).Interface()
+		m := asMessage(v.AsValueOf(goType.Elem()))
 		if err := proto.IsInitialized(m); err != nil {
 			return err
 		}
@@ -327,18 +446,26 @@
 	return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
 }
 
+func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
+	p := pointerOfIface(ival)
+	n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
+	return ival, n, err
+}
+
 func isInitMessageSliceIface(ival interface{}) error {
 	p := pointerOfIface(ival)
 	return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
 }
 
 var coderMessageSliceIface = ifaceCoderFuncs{
-	size:    sizeMessageSliceIface,
-	marshal: appendMessageSliceIface,
-	isInit:  isInitMessageSliceIface,
+	size:      sizeMessageSliceIface,
+	marshal:   appendMessageSliceIface,
+	unmarshal: consumeMessageSliceIface,
+	isInit:    isInitMessageSliceIface,
 }
 
 func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
+	num := fd.Number()
 	if fi, ok := getMessageInfo(ft); ok {
 		return pointerCoderFuncs{
 			size: func(p pointer, tagsize int, opts marshalOptions) int {
@@ -347,6 +474,9 @@
 			marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 				return appendGroupSliceInfo(b, p, wiretag, fi, opts)
 			},
+			unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+				return consumeGroupSliceInfo(b, p, num, wtyp, fi, opts)
+			},
 			isInit: func(p pointer) error {
 				return isInitMessageSliceInfo(p, fi)
 			},
@@ -359,6 +489,9 @@
 		marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 			return appendGroupSlice(b, p, wiretag, ft, opts)
 		},
+		unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+			return consumeGroupSlice(b, p, num, wtyp, ft, opts)
+		},
 		isInit: func(p pointer) error {
 			return isInitMessageSlice(p, ft)
 		},
@@ -369,7 +502,7 @@
 	s := p.PointerSlice()
 	n := 0
 	for _, v := range s {
-		m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
+		m := asMessage(v.AsValueOf(messageType.Elem()))
 		n += 2*tagsize + proto.Size(m)
 	}
 	return n
@@ -379,7 +512,7 @@
 	s := p.PointerSlice()
 	var err error
 	for _, v := range s {
-		m := Export{}.MessageOf(v.AsValueOf(messageType.Elem()).Interface()).Interface()
+		m := asMessage(v.AsValueOf(messageType.Elem()))
 		b = wire.AppendVarint(b, wiretag) // start group
 		b, err = opts.Options().MarshalAppend(b, m)
 		if err != nil {
@@ -390,6 +523,22 @@
 	return b, nil
 }
 
+func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goType reflect.Type, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.StartGroupType {
+		return 0, errUnknown
+	}
+	b, n := wire.ConsumeGroup(num, b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	mp := reflect.New(goType.Elem())
+	if err := opts.Options().Unmarshal(b, asMessage(mp)); err != nil {
+		return 0, err
+	}
+	p.AppendPointerSlice(pointerOfValue(mp))
+	return n, nil
+}
+
 func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
 	s := p.PointerSlice()
 	n := 0
@@ -413,6 +562,20 @@
 	return b, nil
 }
 
+func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (int, error) {
+	if wtyp != wire.StartGroupType {
+		return 0, errUnknown
+	}
+	m := reflect.New(mi.GoType.Elem()).Interface()
+	mp := pointerOfIface(m)
+	n, err := mi.unmarshalPointer(b, mp, num, opts)
+	if err != nil {
+		return 0, err
+	}
+	p.AppendPointerSlice(mp)
+	return n, nil
+}
+
 func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
 	p := pointerOfIface(ival)
 	return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
@@ -423,10 +586,17 @@
 	return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
 }
 
+func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
+	p := pointerOfIface(ival)
+	n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
+	return ival, n, err
+}
+
 var coderGroupSliceIface = ifaceCoderFuncs{
-	size:    sizeGroupSliceIface,
-	marshal: appendGroupSliceIface,
-	isInit:  isInitMessageSliceIface,
+	size:      sizeGroupSliceIface,
+	marshal:   appendGroupSliceIface,
+	unmarshal: consumeGroupSliceIface,
+	isInit:    isInitMessageSliceIface,
 }
 
 // Enums
@@ -443,9 +613,23 @@
 	return b, nil
 }
 
+func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	rv := reflect.New(reflect.TypeOf(ival)).Elem()
+	rv.SetInt(int64(v))
+	return rv.Interface(), n, nil
+}
+
 var coderEnumIface = ifaceCoderFuncs{
-	size:    sizeEnumIface,
-	marshal: appendEnumIface,
+	size:      sizeEnumIface,
+	marshal:   appendEnumIface,
+	unmarshal: consumeEnumIface,
 }
 
 func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
@@ -471,9 +655,47 @@
 	return b, nil
 }
 
+func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
+	n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
+	return ival, n, err
+}
+
+func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	s = s.Elem() // *[]E -> []E
+	if wtyp == wire.BytesType {
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			rv := reflect.New(s.Type().Elem()).Elem()
+			rv.SetInt(int64(v))
+			s.Set(reflect.Append(s, rv))
+			b = b[n:]
+		}
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	rv := reflect.New(s.Type().Elem()).Elem()
+	rv.SetInt(int64(v))
+	s.Set(reflect.Append(s, rv))
+	return n, nil
+}
+
 var coderEnumSliceIface = ifaceCoderFuncs{
-	size:    sizeEnumSliceIface,
-	marshal: appendEnumSliceIface,
+	size:      sizeEnumSliceIface,
+	marshal:   appendEnumSliceIface,
+	unmarshal: consumeEnumSliceIface,
 }
 
 // Strings with UTF8 validation.
@@ -488,9 +710,25 @@
 	return b, nil
 }
 
+func consumeStringValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	if !utf8.ValidString(v) {
+		return 0, errInvalidUTF8{}
+	}
+	*p.String() = v
+	return n, nil
+}
+
 var coderStringValidateUTF8 = pointerCoderFuncs{
-	size:    sizeString,
-	marshal: appendStringValidateUTF8,
+	size:      sizeString,
+	marshal:   appendStringValidateUTF8,
+	unmarshal: consumeStringValidateUTF8,
 }
 
 func appendStringNoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
@@ -507,8 +745,9 @@
 }
 
 var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{
-	size:    sizeStringNoZero,
-	marshal: appendStringNoZeroValidateUTF8,
+	size:      sizeStringNoZero,
+	marshal:   appendStringNoZeroValidateUTF8,
+	unmarshal: consumeStringValidateUTF8,
 }
 
 func sizeStringSliceValidateUTF8(p pointer, tagsize int, _ marshalOptions) (size int) {
@@ -526,15 +765,32 @@
 		b = wire.AppendVarint(b, wiretag)
 		b = wire.AppendString(b, v)
 		if !utf8.ValidString(v) {
-			err = errInvalidUTF8{}
+			return b, errInvalidUTF8{}
 		}
 	}
 	return b, err
 }
 
+func consumeStringSliceValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	sp := p.StringSlice()
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	if !utf8.ValidString(v) {
+		return 0, errInvalidUTF8{}
+	}
+	*sp = append(*sp, v)
+	return n, nil
+}
+
 var coderStringSliceValidateUTF8 = pointerCoderFuncs{
-	size:    sizeStringSliceValidateUTF8,
-	marshal: appendStringSliceValidateUTF8,
+	size:      sizeStringSliceValidateUTF8,
+	marshal:   appendStringSliceValidateUTF8,
+	unmarshal: consumeStringSliceValidateUTF8,
 }
 
 func sizeStringIfaceValidateUTF8(ival interface{}, tagsize int, _ marshalOptions) int {
@@ -552,9 +808,24 @@
 	return b, nil
 }
 
+func consumeStringIfaceValidateUTF8(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.BytesType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	if !utf8.ValidString(v) {
+		return nil, 0, errInvalidUTF8{}
+	}
+	return v, n, nil
+}
+
 var coderStringIfaceValidateUTF8 = ifaceCoderFuncs{
-	size:    sizeStringIfaceValidateUTF8,
-	marshal: appendStringIfaceValidateUTF8,
+	size:      sizeStringIfaceValidateUTF8,
+	marshal:   appendStringIfaceValidateUTF8,
+	unmarshal: consumeStringIfaceValidateUTF8,
 }
 
 func asMessage(v reflect.Value) pref.ProtoMessage {
diff --git a/internal/impl/codec_gen.go b/internal/impl/codec_gen.go
index 7dbb0bc..f04e3c5 100644
--- a/internal/impl/codec_gen.go
+++ b/internal/impl/codec_gen.go
@@ -27,9 +27,23 @@
 	return b, nil
 }
 
+// consumeBool wire decodes a bool pointer as a Bool.
+func consumeBool(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Bool() = wire.DecodeBool(v)
+	return n, nil
+}
+
 var coderBool = pointerCoderFuncs{
-	size:    sizeBool,
-	marshal: appendBool,
+	size:      sizeBool,
+	marshal:   appendBool,
+	unmarshal: consumeBool,
 }
 
 // sizeBool returns the size of wire encoding a bool pointer as a Bool.
@@ -55,8 +69,9 @@
 }
 
 var coderBoolNoZero = pointerCoderFuncs{
-	size:    sizeBoolNoZero,
-	marshal: appendBoolNoZero,
+	size:      sizeBoolNoZero,
+	marshal:   appendBoolNoZero,
+	unmarshal: consumeBool,
 }
 
 // sizeBoolPtr returns the size of wire encoding a *bool pointer as a Bool.
@@ -66,7 +81,7 @@
 	return tagsize + wire.SizeVarint(wire.EncodeBool(v))
 }
 
-// appendBool wire encodes a *bool pointer as a Bool.
+// appendBoolPtr wire encodes a *bool pointer as a Bool.
 // It panics if the pointer is nil.
 func appendBoolPtr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.BoolPtr()
@@ -75,9 +90,27 @@
 	return b, nil
 }
 
+// consumeBoolPtr wire decodes a *bool pointer as a Bool.
+func consumeBoolPtr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.BoolPtr()
+	if *vp == nil {
+		*vp = new(bool)
+	}
+	**vp = wire.DecodeBool(v)
+	return n, nil
+}
+
 var coderBoolPtr = pointerCoderFuncs{
-	size:    sizeBoolPtr,
-	marshal: appendBoolPtr,
+	size:      sizeBoolPtr,
+	marshal:   appendBoolPtr,
+	unmarshal: consumeBoolPtr,
 }
 
 // sizeBoolSlice returns the size of wire encoding a []bool pointer as a repeated Bool.
@@ -99,9 +132,41 @@
 	return b, nil
 }
 
+// consumeBoolSlice wire decodes a []bool pointer as a repeated Bool.
+func consumeBoolSlice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.BoolSlice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, wire.DecodeBool(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, wire.DecodeBool(v))
+	return n, nil
+}
+
 var coderBoolSlice = pointerCoderFuncs{
-	size:    sizeBoolSlice,
-	marshal: appendBoolSlice,
+	size:      sizeBoolSlice,
+	marshal:   appendBoolSlice,
+	unmarshal: consumeBoolSlice,
 }
 
 // sizeBoolPackedSlice returns the size of wire encoding a []bool pointer as a packed repeated Bool.
@@ -136,8 +201,9 @@
 }
 
 var coderBoolPackedSlice = pointerCoderFuncs{
-	size:    sizeBoolPackedSlice,
-	marshal: appendBoolPackedSlice,
+	size:      sizeBoolPackedSlice,
+	marshal:   appendBoolPackedSlice,
+	unmarshal: consumeBoolSlice,
 }
 
 // sizeBoolIface returns the size of wire encoding a bool value as a Bool.
@@ -154,9 +220,22 @@
 	return b, nil
 }
 
+// consumeBoolIface decodes a bool value as a Bool.
+func consumeBoolIface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return wire.DecodeBool(v), n, nil
+}
+
 var coderBoolIface = ifaceCoderFuncs{
-	size:    sizeBoolIface,
-	marshal: appendBoolIface,
+	size:      sizeBoolIface,
+	marshal:   appendBoolIface,
+	unmarshal: consumeBoolIface,
 }
 
 // sizeBoolSliceIface returns the size of wire encoding a []bool value as a repeated Bool.
@@ -178,9 +257,41 @@
 	return b, nil
 }
 
+// consumeBoolSliceIface wire decodes a []bool value as a repeated Bool.
+func consumeBoolSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]bool)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, wire.DecodeBool(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, wire.DecodeBool(v))
+	return ival, n, nil
+}
+
 var coderBoolSliceIface = ifaceCoderFuncs{
-	size:    sizeBoolSliceIface,
-	marshal: appendBoolSliceIface,
+	size:      sizeBoolSliceIface,
+	marshal:   appendBoolSliceIface,
+	unmarshal: consumeBoolSliceIface,
 }
 
 // sizeInt32 returns the size of wire encoding a int32 pointer as a Int32.
@@ -197,9 +308,23 @@
 	return b, nil
 }
 
+// consumeInt32 wire decodes a int32 pointer as a Int32.
+func consumeInt32(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int32() = int32(v)
+	return n, nil
+}
+
 var coderInt32 = pointerCoderFuncs{
-	size:    sizeInt32,
-	marshal: appendInt32,
+	size:      sizeInt32,
+	marshal:   appendInt32,
+	unmarshal: consumeInt32,
 }
 
 // sizeInt32 returns the size of wire encoding a int32 pointer as a Int32.
@@ -225,8 +350,9 @@
 }
 
 var coderInt32NoZero = pointerCoderFuncs{
-	size:    sizeInt32NoZero,
-	marshal: appendInt32NoZero,
+	size:      sizeInt32NoZero,
+	marshal:   appendInt32NoZero,
+	unmarshal: consumeInt32,
 }
 
 // sizeInt32Ptr returns the size of wire encoding a *int32 pointer as a Int32.
@@ -236,7 +362,7 @@
 	return tagsize + wire.SizeVarint(uint64(v))
 }
 
-// appendInt32 wire encodes a *int32 pointer as a Int32.
+// appendInt32Ptr wire encodes a *int32 pointer as a Int32.
 // It panics if the pointer is nil.
 func appendInt32Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int32Ptr()
@@ -245,9 +371,27 @@
 	return b, nil
 }
 
+// consumeInt32Ptr wire decodes a *int32 pointer as a Int32.
+func consumeInt32Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int32Ptr()
+	if *vp == nil {
+		*vp = new(int32)
+	}
+	**vp = int32(v)
+	return n, nil
+}
+
 var coderInt32Ptr = pointerCoderFuncs{
-	size:    sizeInt32Ptr,
-	marshal: appendInt32Ptr,
+	size:      sizeInt32Ptr,
+	marshal:   appendInt32Ptr,
+	unmarshal: consumeInt32Ptr,
 }
 
 // sizeInt32Slice returns the size of wire encoding a []int32 pointer as a repeated Int32.
@@ -269,9 +413,41 @@
 	return b, nil
 }
 
+// consumeInt32Slice wire decodes a []int32 pointer as a repeated Int32.
+func consumeInt32Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, int32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(v))
+	return n, nil
+}
+
 var coderInt32Slice = pointerCoderFuncs{
-	size:    sizeInt32Slice,
-	marshal: appendInt32Slice,
+	size:      sizeInt32Slice,
+	marshal:   appendInt32Slice,
+	unmarshal: consumeInt32Slice,
 }
 
 // sizeInt32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Int32.
@@ -306,8 +482,9 @@
 }
 
 var coderInt32PackedSlice = pointerCoderFuncs{
-	size:    sizeInt32PackedSlice,
-	marshal: appendInt32PackedSlice,
+	size:      sizeInt32PackedSlice,
+	marshal:   appendInt32PackedSlice,
+	unmarshal: consumeInt32Slice,
 }
 
 // sizeInt32Iface returns the size of wire encoding a int32 value as a Int32.
@@ -324,9 +501,22 @@
 	return b, nil
 }
 
+// consumeInt32Iface decodes a int32 value as a Int32.
+func consumeInt32Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return int32(v), n, nil
+}
+
 var coderInt32Iface = ifaceCoderFuncs{
-	size:    sizeInt32Iface,
-	marshal: appendInt32Iface,
+	size:      sizeInt32Iface,
+	marshal:   appendInt32Iface,
+	unmarshal: consumeInt32Iface,
 }
 
 // sizeInt32SliceIface returns the size of wire encoding a []int32 value as a repeated Int32.
@@ -348,9 +538,41 @@
 	return b, nil
 }
 
+// consumeInt32SliceIface wire decodes a []int32 value as a repeated Int32.
+func consumeInt32SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, int32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(v))
+	return ival, n, nil
+}
+
 var coderInt32SliceIface = ifaceCoderFuncs{
-	size:    sizeInt32SliceIface,
-	marshal: appendInt32SliceIface,
+	size:      sizeInt32SliceIface,
+	marshal:   appendInt32SliceIface,
+	unmarshal: consumeInt32SliceIface,
 }
 
 // sizeSint32 returns the size of wire encoding a int32 pointer as a Sint32.
@@ -367,9 +589,23 @@
 	return b, nil
 }
 
+// consumeSint32 wire decodes a int32 pointer as a Sint32.
+func consumeSint32(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int32() = int32(wire.DecodeZigZag(v & math.MaxUint32))
+	return n, nil
+}
+
 var coderSint32 = pointerCoderFuncs{
-	size:    sizeSint32,
-	marshal: appendSint32,
+	size:      sizeSint32,
+	marshal:   appendSint32,
+	unmarshal: consumeSint32,
 }
 
 // sizeSint32 returns the size of wire encoding a int32 pointer as a Sint32.
@@ -395,8 +631,9 @@
 }
 
 var coderSint32NoZero = pointerCoderFuncs{
-	size:    sizeSint32NoZero,
-	marshal: appendSint32NoZero,
+	size:      sizeSint32NoZero,
+	marshal:   appendSint32NoZero,
+	unmarshal: consumeSint32,
 }
 
 // sizeSint32Ptr returns the size of wire encoding a *int32 pointer as a Sint32.
@@ -406,7 +643,7 @@
 	return tagsize + wire.SizeVarint(wire.EncodeZigZag(int64(v)))
 }
 
-// appendSint32 wire encodes a *int32 pointer as a Sint32.
+// appendSint32Ptr wire encodes a *int32 pointer as a Sint32.
 // It panics if the pointer is nil.
 func appendSint32Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int32Ptr()
@@ -415,9 +652,27 @@
 	return b, nil
 }
 
+// consumeSint32Ptr wire decodes a *int32 pointer as a Sint32.
+func consumeSint32Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int32Ptr()
+	if *vp == nil {
+		*vp = new(int32)
+	}
+	**vp = int32(wire.DecodeZigZag(v & math.MaxUint32))
+	return n, nil
+}
+
 var coderSint32Ptr = pointerCoderFuncs{
-	size:    sizeSint32Ptr,
-	marshal: appendSint32Ptr,
+	size:      sizeSint32Ptr,
+	marshal:   appendSint32Ptr,
+	unmarshal: consumeSint32Ptr,
 }
 
 // sizeSint32Slice returns the size of wire encoding a []int32 pointer as a repeated Sint32.
@@ -439,9 +694,41 @@
 	return b, nil
 }
 
+// consumeSint32Slice wire decodes a []int32 pointer as a repeated Sint32.
+func consumeSint32Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, int32(wire.DecodeZigZag(v&math.MaxUint32)))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(wire.DecodeZigZag(v&math.MaxUint32)))
+	return n, nil
+}
+
 var coderSint32Slice = pointerCoderFuncs{
-	size:    sizeSint32Slice,
-	marshal: appendSint32Slice,
+	size:      sizeSint32Slice,
+	marshal:   appendSint32Slice,
+	unmarshal: consumeSint32Slice,
 }
 
 // sizeSint32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sint32.
@@ -476,8 +763,9 @@
 }
 
 var coderSint32PackedSlice = pointerCoderFuncs{
-	size:    sizeSint32PackedSlice,
-	marshal: appendSint32PackedSlice,
+	size:      sizeSint32PackedSlice,
+	marshal:   appendSint32PackedSlice,
+	unmarshal: consumeSint32Slice,
 }
 
 // sizeSint32Iface returns the size of wire encoding a int32 value as a Sint32.
@@ -494,9 +782,22 @@
 	return b, nil
 }
 
+// consumeSint32Iface decodes a int32 value as a Sint32.
+func consumeSint32Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return int32(wire.DecodeZigZag(v & math.MaxUint32)), n, nil
+}
+
 var coderSint32Iface = ifaceCoderFuncs{
-	size:    sizeSint32Iface,
-	marshal: appendSint32Iface,
+	size:      sizeSint32Iface,
+	marshal:   appendSint32Iface,
+	unmarshal: consumeSint32Iface,
 }
 
 // sizeSint32SliceIface returns the size of wire encoding a []int32 value as a repeated Sint32.
@@ -518,9 +819,41 @@
 	return b, nil
 }
 
+// consumeSint32SliceIface wire decodes a []int32 value as a repeated Sint32.
+func consumeSint32SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, int32(wire.DecodeZigZag(v&math.MaxUint32)))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(wire.DecodeZigZag(v&math.MaxUint32)))
+	return ival, n, nil
+}
+
 var coderSint32SliceIface = ifaceCoderFuncs{
-	size:    sizeSint32SliceIface,
-	marshal: appendSint32SliceIface,
+	size:      sizeSint32SliceIface,
+	marshal:   appendSint32SliceIface,
+	unmarshal: consumeSint32SliceIface,
 }
 
 // sizeUint32 returns the size of wire encoding a uint32 pointer as a Uint32.
@@ -537,9 +870,23 @@
 	return b, nil
 }
 
+// consumeUint32 wire decodes a uint32 pointer as a Uint32.
+func consumeUint32(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Uint32() = uint32(v)
+	return n, nil
+}
+
 var coderUint32 = pointerCoderFuncs{
-	size:    sizeUint32,
-	marshal: appendUint32,
+	size:      sizeUint32,
+	marshal:   appendUint32,
+	unmarshal: consumeUint32,
 }
 
 // sizeUint32 returns the size of wire encoding a uint32 pointer as a Uint32.
@@ -565,8 +912,9 @@
 }
 
 var coderUint32NoZero = pointerCoderFuncs{
-	size:    sizeUint32NoZero,
-	marshal: appendUint32NoZero,
+	size:      sizeUint32NoZero,
+	marshal:   appendUint32NoZero,
+	unmarshal: consumeUint32,
 }
 
 // sizeUint32Ptr returns the size of wire encoding a *uint32 pointer as a Uint32.
@@ -576,7 +924,7 @@
 	return tagsize + wire.SizeVarint(uint64(v))
 }
 
-// appendUint32 wire encodes a *uint32 pointer as a Uint32.
+// appendUint32Ptr wire encodes a *uint32 pointer as a Uint32.
 // It panics if the pointer is nil.
 func appendUint32Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Uint32Ptr()
@@ -585,9 +933,27 @@
 	return b, nil
 }
 
+// consumeUint32Ptr wire decodes a *uint32 pointer as a Uint32.
+func consumeUint32Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Uint32Ptr()
+	if *vp == nil {
+		*vp = new(uint32)
+	}
+	**vp = uint32(v)
+	return n, nil
+}
+
 var coderUint32Ptr = pointerCoderFuncs{
-	size:    sizeUint32Ptr,
-	marshal: appendUint32Ptr,
+	size:      sizeUint32Ptr,
+	marshal:   appendUint32Ptr,
+	unmarshal: consumeUint32Ptr,
 }
 
 // sizeUint32Slice returns the size of wire encoding a []uint32 pointer as a repeated Uint32.
@@ -609,9 +975,41 @@
 	return b, nil
 }
 
+// consumeUint32Slice wire decodes a []uint32 pointer as a repeated Uint32.
+func consumeUint32Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Uint32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, uint32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, uint32(v))
+	return n, nil
+}
+
 var coderUint32Slice = pointerCoderFuncs{
-	size:    sizeUint32Slice,
-	marshal: appendUint32Slice,
+	size:      sizeUint32Slice,
+	marshal:   appendUint32Slice,
+	unmarshal: consumeUint32Slice,
 }
 
 // sizeUint32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Uint32.
@@ -646,8 +1044,9 @@
 }
 
 var coderUint32PackedSlice = pointerCoderFuncs{
-	size:    sizeUint32PackedSlice,
-	marshal: appendUint32PackedSlice,
+	size:      sizeUint32PackedSlice,
+	marshal:   appendUint32PackedSlice,
+	unmarshal: consumeUint32Slice,
 }
 
 // sizeUint32Iface returns the size of wire encoding a uint32 value as a Uint32.
@@ -664,9 +1063,22 @@
 	return b, nil
 }
 
+// consumeUint32Iface decodes a uint32 value as a Uint32.
+func consumeUint32Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return uint32(v), n, nil
+}
+
 var coderUint32Iface = ifaceCoderFuncs{
-	size:    sizeUint32Iface,
-	marshal: appendUint32Iface,
+	size:      sizeUint32Iface,
+	marshal:   appendUint32Iface,
+	unmarshal: consumeUint32Iface,
 }
 
 // sizeUint32SliceIface returns the size of wire encoding a []uint32 value as a repeated Uint32.
@@ -688,9 +1100,41 @@
 	return b, nil
 }
 
+// consumeUint32SliceIface wire decodes a []uint32 value as a repeated Uint32.
+func consumeUint32SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]uint32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, uint32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, uint32(v))
+	return ival, n, nil
+}
+
 var coderUint32SliceIface = ifaceCoderFuncs{
-	size:    sizeUint32SliceIface,
-	marshal: appendUint32SliceIface,
+	size:      sizeUint32SliceIface,
+	marshal:   appendUint32SliceIface,
+	unmarshal: consumeUint32SliceIface,
 }
 
 // sizeInt64 returns the size of wire encoding a int64 pointer as a Int64.
@@ -707,9 +1151,23 @@
 	return b, nil
 }
 
+// consumeInt64 wire decodes a int64 pointer as a Int64.
+func consumeInt64(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int64() = int64(v)
+	return n, nil
+}
+
 var coderInt64 = pointerCoderFuncs{
-	size:    sizeInt64,
-	marshal: appendInt64,
+	size:      sizeInt64,
+	marshal:   appendInt64,
+	unmarshal: consumeInt64,
 }
 
 // sizeInt64 returns the size of wire encoding a int64 pointer as a Int64.
@@ -735,8 +1193,9 @@
 }
 
 var coderInt64NoZero = pointerCoderFuncs{
-	size:    sizeInt64NoZero,
-	marshal: appendInt64NoZero,
+	size:      sizeInt64NoZero,
+	marshal:   appendInt64NoZero,
+	unmarshal: consumeInt64,
 }
 
 // sizeInt64Ptr returns the size of wire encoding a *int64 pointer as a Int64.
@@ -746,7 +1205,7 @@
 	return tagsize + wire.SizeVarint(uint64(v))
 }
 
-// appendInt64 wire encodes a *int64 pointer as a Int64.
+// appendInt64Ptr wire encodes a *int64 pointer as a Int64.
 // It panics if the pointer is nil.
 func appendInt64Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int64Ptr()
@@ -755,9 +1214,27 @@
 	return b, nil
 }
 
+// consumeInt64Ptr wire decodes a *int64 pointer as a Int64.
+func consumeInt64Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int64Ptr()
+	if *vp == nil {
+		*vp = new(int64)
+	}
+	**vp = int64(v)
+	return n, nil
+}
+
 var coderInt64Ptr = pointerCoderFuncs{
-	size:    sizeInt64Ptr,
-	marshal: appendInt64Ptr,
+	size:      sizeInt64Ptr,
+	marshal:   appendInt64Ptr,
+	unmarshal: consumeInt64Ptr,
 }
 
 // sizeInt64Slice returns the size of wire encoding a []int64 pointer as a repeated Int64.
@@ -779,9 +1256,41 @@
 	return b, nil
 }
 
+// consumeInt64Slice wire decodes a []int64 pointer as a repeated Int64.
+func consumeInt64Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, int64(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int64(v))
+	return n, nil
+}
+
 var coderInt64Slice = pointerCoderFuncs{
-	size:    sizeInt64Slice,
-	marshal: appendInt64Slice,
+	size:      sizeInt64Slice,
+	marshal:   appendInt64Slice,
+	unmarshal: consumeInt64Slice,
 }
 
 // sizeInt64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Int64.
@@ -816,8 +1325,9 @@
 }
 
 var coderInt64PackedSlice = pointerCoderFuncs{
-	size:    sizeInt64PackedSlice,
-	marshal: appendInt64PackedSlice,
+	size:      sizeInt64PackedSlice,
+	marshal:   appendInt64PackedSlice,
+	unmarshal: consumeInt64Slice,
 }
 
 // sizeInt64Iface returns the size of wire encoding a int64 value as a Int64.
@@ -834,9 +1344,22 @@
 	return b, nil
 }
 
+// consumeInt64Iface decodes a int64 value as a Int64.
+func consumeInt64Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return int64(v), n, nil
+}
+
 var coderInt64Iface = ifaceCoderFuncs{
-	size:    sizeInt64Iface,
-	marshal: appendInt64Iface,
+	size:      sizeInt64Iface,
+	marshal:   appendInt64Iface,
+	unmarshal: consumeInt64Iface,
 }
 
 // sizeInt64SliceIface returns the size of wire encoding a []int64 value as a repeated Int64.
@@ -858,9 +1381,41 @@
 	return b, nil
 }
 
+// consumeInt64SliceIface wire decodes a []int64 value as a repeated Int64.
+func consumeInt64SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, int64(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int64(v))
+	return ival, n, nil
+}
+
 var coderInt64SliceIface = ifaceCoderFuncs{
-	size:    sizeInt64SliceIface,
-	marshal: appendInt64SliceIface,
+	size:      sizeInt64SliceIface,
+	marshal:   appendInt64SliceIface,
+	unmarshal: consumeInt64SliceIface,
 }
 
 // sizeSint64 returns the size of wire encoding a int64 pointer as a Sint64.
@@ -877,9 +1432,23 @@
 	return b, nil
 }
 
+// consumeSint64 wire decodes a int64 pointer as a Sint64.
+func consumeSint64(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int64() = wire.DecodeZigZag(v)
+	return n, nil
+}
+
 var coderSint64 = pointerCoderFuncs{
-	size:    sizeSint64,
-	marshal: appendSint64,
+	size:      sizeSint64,
+	marshal:   appendSint64,
+	unmarshal: consumeSint64,
 }
 
 // sizeSint64 returns the size of wire encoding a int64 pointer as a Sint64.
@@ -905,8 +1474,9 @@
 }
 
 var coderSint64NoZero = pointerCoderFuncs{
-	size:    sizeSint64NoZero,
-	marshal: appendSint64NoZero,
+	size:      sizeSint64NoZero,
+	marshal:   appendSint64NoZero,
+	unmarshal: consumeSint64,
 }
 
 // sizeSint64Ptr returns the size of wire encoding a *int64 pointer as a Sint64.
@@ -916,7 +1486,7 @@
 	return tagsize + wire.SizeVarint(wire.EncodeZigZag(v))
 }
 
-// appendSint64 wire encodes a *int64 pointer as a Sint64.
+// appendSint64Ptr wire encodes a *int64 pointer as a Sint64.
 // It panics if the pointer is nil.
 func appendSint64Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int64Ptr()
@@ -925,9 +1495,27 @@
 	return b, nil
 }
 
+// consumeSint64Ptr wire decodes a *int64 pointer as a Sint64.
+func consumeSint64Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int64Ptr()
+	if *vp == nil {
+		*vp = new(int64)
+	}
+	**vp = wire.DecodeZigZag(v)
+	return n, nil
+}
+
 var coderSint64Ptr = pointerCoderFuncs{
-	size:    sizeSint64Ptr,
-	marshal: appendSint64Ptr,
+	size:      sizeSint64Ptr,
+	marshal:   appendSint64Ptr,
+	unmarshal: consumeSint64Ptr,
 }
 
 // sizeSint64Slice returns the size of wire encoding a []int64 pointer as a repeated Sint64.
@@ -949,9 +1537,41 @@
 	return b, nil
 }
 
+// consumeSint64Slice wire decodes a []int64 pointer as a repeated Sint64.
+func consumeSint64Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, wire.DecodeZigZag(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, wire.DecodeZigZag(v))
+	return n, nil
+}
+
 var coderSint64Slice = pointerCoderFuncs{
-	size:    sizeSint64Slice,
-	marshal: appendSint64Slice,
+	size:      sizeSint64Slice,
+	marshal:   appendSint64Slice,
+	unmarshal: consumeSint64Slice,
 }
 
 // sizeSint64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sint64.
@@ -986,8 +1606,9 @@
 }
 
 var coderSint64PackedSlice = pointerCoderFuncs{
-	size:    sizeSint64PackedSlice,
-	marshal: appendSint64PackedSlice,
+	size:      sizeSint64PackedSlice,
+	marshal:   appendSint64PackedSlice,
+	unmarshal: consumeSint64Slice,
 }
 
 // sizeSint64Iface returns the size of wire encoding a int64 value as a Sint64.
@@ -1004,9 +1625,22 @@
 	return b, nil
 }
 
+// consumeSint64Iface decodes a int64 value as a Sint64.
+func consumeSint64Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return wire.DecodeZigZag(v), n, nil
+}
+
 var coderSint64Iface = ifaceCoderFuncs{
-	size:    sizeSint64Iface,
-	marshal: appendSint64Iface,
+	size:      sizeSint64Iface,
+	marshal:   appendSint64Iface,
+	unmarshal: consumeSint64Iface,
 }
 
 // sizeSint64SliceIface returns the size of wire encoding a []int64 value as a repeated Sint64.
@@ -1028,9 +1662,41 @@
 	return b, nil
 }
 
+// consumeSint64SliceIface wire decodes a []int64 value as a repeated Sint64.
+func consumeSint64SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, wire.DecodeZigZag(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, wire.DecodeZigZag(v))
+	return ival, n, nil
+}
+
 var coderSint64SliceIface = ifaceCoderFuncs{
-	size:    sizeSint64SliceIface,
-	marshal: appendSint64SliceIface,
+	size:      sizeSint64SliceIface,
+	marshal:   appendSint64SliceIface,
+	unmarshal: consumeSint64SliceIface,
 }
 
 // sizeUint64 returns the size of wire encoding a uint64 pointer as a Uint64.
@@ -1047,9 +1713,23 @@
 	return b, nil
 }
 
+// consumeUint64 wire decodes a uint64 pointer as a Uint64.
+func consumeUint64(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Uint64() = v
+	return n, nil
+}
+
 var coderUint64 = pointerCoderFuncs{
-	size:    sizeUint64,
-	marshal: appendUint64,
+	size:      sizeUint64,
+	marshal:   appendUint64,
+	unmarshal: consumeUint64,
 }
 
 // sizeUint64 returns the size of wire encoding a uint64 pointer as a Uint64.
@@ -1075,8 +1755,9 @@
 }
 
 var coderUint64NoZero = pointerCoderFuncs{
-	size:    sizeUint64NoZero,
-	marshal: appendUint64NoZero,
+	size:      sizeUint64NoZero,
+	marshal:   appendUint64NoZero,
+	unmarshal: consumeUint64,
 }
 
 // sizeUint64Ptr returns the size of wire encoding a *uint64 pointer as a Uint64.
@@ -1086,7 +1767,7 @@
 	return tagsize + wire.SizeVarint(v)
 }
 
-// appendUint64 wire encodes a *uint64 pointer as a Uint64.
+// appendUint64Ptr wire encodes a *uint64 pointer as a Uint64.
 // It panics if the pointer is nil.
 func appendUint64Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Uint64Ptr()
@@ -1095,9 +1776,27 @@
 	return b, nil
 }
 
+// consumeUint64Ptr wire decodes a *uint64 pointer as a Uint64.
+func consumeUint64Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Uint64Ptr()
+	if *vp == nil {
+		*vp = new(uint64)
+	}
+	**vp = v
+	return n, nil
+}
+
 var coderUint64Ptr = pointerCoderFuncs{
-	size:    sizeUint64Ptr,
-	marshal: appendUint64Ptr,
+	size:      sizeUint64Ptr,
+	marshal:   appendUint64Ptr,
+	unmarshal: consumeUint64Ptr,
 }
 
 // sizeUint64Slice returns the size of wire encoding a []uint64 pointer as a repeated Uint64.
@@ -1119,9 +1818,41 @@
 	return b, nil
 }
 
+// consumeUint64Slice wire decodes a []uint64 pointer as a repeated Uint64.
+func consumeUint64Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Uint64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return n, nil
+}
+
 var coderUint64Slice = pointerCoderFuncs{
-	size:    sizeUint64Slice,
-	marshal: appendUint64Slice,
+	size:      sizeUint64Slice,
+	marshal:   appendUint64Slice,
+	unmarshal: consumeUint64Slice,
 }
 
 // sizeUint64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Uint64.
@@ -1156,8 +1887,9 @@
 }
 
 var coderUint64PackedSlice = pointerCoderFuncs{
-	size:    sizeUint64PackedSlice,
-	marshal: appendUint64PackedSlice,
+	size:      sizeUint64PackedSlice,
+	marshal:   appendUint64PackedSlice,
+	unmarshal: consumeUint64Slice,
 }
 
 // sizeUint64Iface returns the size of wire encoding a uint64 value as a Uint64.
@@ -1174,9 +1906,22 @@
 	return b, nil
 }
 
+// consumeUint64Iface decodes a uint64 value as a Uint64.
+func consumeUint64Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return v, n, nil
+}
+
 var coderUint64Iface = ifaceCoderFuncs{
-	size:    sizeUint64Iface,
-	marshal: appendUint64Iface,
+	size:      sizeUint64Iface,
+	marshal:   appendUint64Iface,
+	unmarshal: consumeUint64Iface,
 }
 
 // sizeUint64SliceIface returns the size of wire encoding a []uint64 value as a repeated Uint64.
@@ -1198,9 +1943,41 @@
 	return b, nil
 }
 
+// consumeUint64SliceIface wire decodes a []uint64 value as a repeated Uint64.
+func consumeUint64SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]uint64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeVarint(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.VarintType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return ival, n, nil
+}
+
 var coderUint64SliceIface = ifaceCoderFuncs{
-	size:    sizeUint64SliceIface,
-	marshal: appendUint64SliceIface,
+	size:      sizeUint64SliceIface,
+	marshal:   appendUint64SliceIface,
+	unmarshal: consumeUint64SliceIface,
 }
 
 // sizeSfixed32 returns the size of wire encoding a int32 pointer as a Sfixed32.
@@ -1217,9 +1994,23 @@
 	return b, nil
 }
 
+// consumeSfixed32 wire decodes a int32 pointer as a Sfixed32.
+func consumeSfixed32(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int32() = int32(v)
+	return n, nil
+}
+
 var coderSfixed32 = pointerCoderFuncs{
-	size:    sizeSfixed32,
-	marshal: appendSfixed32,
+	size:      sizeSfixed32,
+	marshal:   appendSfixed32,
+	unmarshal: consumeSfixed32,
 }
 
 // sizeSfixed32 returns the size of wire encoding a int32 pointer as a Sfixed32.
@@ -1245,8 +2036,9 @@
 }
 
 var coderSfixed32NoZero = pointerCoderFuncs{
-	size:    sizeSfixed32NoZero,
-	marshal: appendSfixed32NoZero,
+	size:      sizeSfixed32NoZero,
+	marshal:   appendSfixed32NoZero,
+	unmarshal: consumeSfixed32,
 }
 
 // sizeSfixed32Ptr returns the size of wire encoding a *int32 pointer as a Sfixed32.
@@ -1255,7 +2047,7 @@
 	return tagsize + wire.SizeFixed32()
 }
 
-// appendSfixed32 wire encodes a *int32 pointer as a Sfixed32.
+// appendSfixed32Ptr wire encodes a *int32 pointer as a Sfixed32.
 // It panics if the pointer is nil.
 func appendSfixed32Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int32Ptr()
@@ -1264,9 +2056,27 @@
 	return b, nil
 }
 
+// consumeSfixed32Ptr wire decodes a *int32 pointer as a Sfixed32.
+func consumeSfixed32Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int32Ptr()
+	if *vp == nil {
+		*vp = new(int32)
+	}
+	**vp = int32(v)
+	return n, nil
+}
+
 var coderSfixed32Ptr = pointerCoderFuncs{
-	size:    sizeSfixed32Ptr,
-	marshal: appendSfixed32Ptr,
+	size:      sizeSfixed32Ptr,
+	marshal:   appendSfixed32Ptr,
+	unmarshal: consumeSfixed32Ptr,
 }
 
 // sizeSfixed32Slice returns the size of wire encoding a []int32 pointer as a repeated Sfixed32.
@@ -1286,9 +2096,41 @@
 	return b, nil
 }
 
+// consumeSfixed32Slice wire decodes a []int32 pointer as a repeated Sfixed32.
+func consumeSfixed32Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, int32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(v))
+	return n, nil
+}
+
 var coderSfixed32Slice = pointerCoderFuncs{
-	size:    sizeSfixed32Slice,
-	marshal: appendSfixed32Slice,
+	size:      sizeSfixed32Slice,
+	marshal:   appendSfixed32Slice,
+	unmarshal: consumeSfixed32Slice,
 }
 
 // sizeSfixed32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sfixed32.
@@ -1317,8 +2159,9 @@
 }
 
 var coderSfixed32PackedSlice = pointerCoderFuncs{
-	size:    sizeSfixed32PackedSlice,
-	marshal: appendSfixed32PackedSlice,
+	size:      sizeSfixed32PackedSlice,
+	marshal:   appendSfixed32PackedSlice,
+	unmarshal: consumeSfixed32Slice,
 }
 
 // sizeSfixed32Iface returns the size of wire encoding a int32 value as a Sfixed32.
@@ -1334,9 +2177,22 @@
 	return b, nil
 }
 
+// consumeSfixed32Iface decodes a int32 value as a Sfixed32.
+func consumeSfixed32Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return int32(v), n, nil
+}
+
 var coderSfixed32Iface = ifaceCoderFuncs{
-	size:    sizeSfixed32Iface,
-	marshal: appendSfixed32Iface,
+	size:      sizeSfixed32Iface,
+	marshal:   appendSfixed32Iface,
+	unmarshal: consumeSfixed32Iface,
 }
 
 // sizeSfixed32SliceIface returns the size of wire encoding a []int32 value as a repeated Sfixed32.
@@ -1356,9 +2212,41 @@
 	return b, nil
 }
 
+// consumeSfixed32SliceIface wire decodes a []int32 value as a repeated Sfixed32.
+func consumeSfixed32SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, int32(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int32(v))
+	return ival, n, nil
+}
+
 var coderSfixed32SliceIface = ifaceCoderFuncs{
-	size:    sizeSfixed32SliceIface,
-	marshal: appendSfixed32SliceIface,
+	size:      sizeSfixed32SliceIface,
+	marshal:   appendSfixed32SliceIface,
+	unmarshal: consumeSfixed32SliceIface,
 }
 
 // sizeFixed32 returns the size of wire encoding a uint32 pointer as a Fixed32.
@@ -1375,9 +2263,23 @@
 	return b, nil
 }
 
+// consumeFixed32 wire decodes a uint32 pointer as a Fixed32.
+func consumeFixed32(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Uint32() = v
+	return n, nil
+}
+
 var coderFixed32 = pointerCoderFuncs{
-	size:    sizeFixed32,
-	marshal: appendFixed32,
+	size:      sizeFixed32,
+	marshal:   appendFixed32,
+	unmarshal: consumeFixed32,
 }
 
 // sizeFixed32 returns the size of wire encoding a uint32 pointer as a Fixed32.
@@ -1403,8 +2305,9 @@
 }
 
 var coderFixed32NoZero = pointerCoderFuncs{
-	size:    sizeFixed32NoZero,
-	marshal: appendFixed32NoZero,
+	size:      sizeFixed32NoZero,
+	marshal:   appendFixed32NoZero,
+	unmarshal: consumeFixed32,
 }
 
 // sizeFixed32Ptr returns the size of wire encoding a *uint32 pointer as a Fixed32.
@@ -1413,7 +2316,7 @@
 	return tagsize + wire.SizeFixed32()
 }
 
-// appendFixed32 wire encodes a *uint32 pointer as a Fixed32.
+// appendFixed32Ptr wire encodes a *uint32 pointer as a Fixed32.
 // It panics if the pointer is nil.
 func appendFixed32Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Uint32Ptr()
@@ -1422,9 +2325,27 @@
 	return b, nil
 }
 
+// consumeFixed32Ptr wire decodes a *uint32 pointer as a Fixed32.
+func consumeFixed32Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Uint32Ptr()
+	if *vp == nil {
+		*vp = new(uint32)
+	}
+	**vp = v
+	return n, nil
+}
+
 var coderFixed32Ptr = pointerCoderFuncs{
-	size:    sizeFixed32Ptr,
-	marshal: appendFixed32Ptr,
+	size:      sizeFixed32Ptr,
+	marshal:   appendFixed32Ptr,
+	unmarshal: consumeFixed32Ptr,
 }
 
 // sizeFixed32Slice returns the size of wire encoding a []uint32 pointer as a repeated Fixed32.
@@ -1444,9 +2365,41 @@
 	return b, nil
 }
 
+// consumeFixed32Slice wire decodes a []uint32 pointer as a repeated Fixed32.
+func consumeFixed32Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Uint32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return n, nil
+}
+
 var coderFixed32Slice = pointerCoderFuncs{
-	size:    sizeFixed32Slice,
-	marshal: appendFixed32Slice,
+	size:      sizeFixed32Slice,
+	marshal:   appendFixed32Slice,
+	unmarshal: consumeFixed32Slice,
 }
 
 // sizeFixed32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Fixed32.
@@ -1475,8 +2428,9 @@
 }
 
 var coderFixed32PackedSlice = pointerCoderFuncs{
-	size:    sizeFixed32PackedSlice,
-	marshal: appendFixed32PackedSlice,
+	size:      sizeFixed32PackedSlice,
+	marshal:   appendFixed32PackedSlice,
+	unmarshal: consumeFixed32Slice,
 }
 
 // sizeFixed32Iface returns the size of wire encoding a uint32 value as a Fixed32.
@@ -1492,9 +2446,22 @@
 	return b, nil
 }
 
+// consumeFixed32Iface decodes a uint32 value as a Fixed32.
+func consumeFixed32Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return v, n, nil
+}
+
 var coderFixed32Iface = ifaceCoderFuncs{
-	size:    sizeFixed32Iface,
-	marshal: appendFixed32Iface,
+	size:      sizeFixed32Iface,
+	marshal:   appendFixed32Iface,
+	unmarshal: consumeFixed32Iface,
 }
 
 // sizeFixed32SliceIface returns the size of wire encoding a []uint32 value as a repeated Fixed32.
@@ -1514,9 +2481,41 @@
 	return b, nil
 }
 
+// consumeFixed32SliceIface wire decodes a []uint32 value as a repeated Fixed32.
+func consumeFixed32SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]uint32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return ival, n, nil
+}
+
 var coderFixed32SliceIface = ifaceCoderFuncs{
-	size:    sizeFixed32SliceIface,
-	marshal: appendFixed32SliceIface,
+	size:      sizeFixed32SliceIface,
+	marshal:   appendFixed32SliceIface,
+	unmarshal: consumeFixed32SliceIface,
 }
 
 // sizeFloat returns the size of wire encoding a float32 pointer as a Float.
@@ -1533,9 +2532,23 @@
 	return b, nil
 }
 
+// consumeFloat wire decodes a float32 pointer as a Float.
+func consumeFloat(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Float32() = math.Float32frombits(v)
+	return n, nil
+}
+
 var coderFloat = pointerCoderFuncs{
-	size:    sizeFloat,
-	marshal: appendFloat,
+	size:      sizeFloat,
+	marshal:   appendFloat,
+	unmarshal: consumeFloat,
 }
 
 // sizeFloat returns the size of wire encoding a float32 pointer as a Float.
@@ -1561,8 +2574,9 @@
 }
 
 var coderFloatNoZero = pointerCoderFuncs{
-	size:    sizeFloatNoZero,
-	marshal: appendFloatNoZero,
+	size:      sizeFloatNoZero,
+	marshal:   appendFloatNoZero,
+	unmarshal: consumeFloat,
 }
 
 // sizeFloatPtr returns the size of wire encoding a *float32 pointer as a Float.
@@ -1571,7 +2585,7 @@
 	return tagsize + wire.SizeFixed32()
 }
 
-// appendFloat wire encodes a *float32 pointer as a Float.
+// appendFloatPtr wire encodes a *float32 pointer as a Float.
 // It panics if the pointer is nil.
 func appendFloatPtr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Float32Ptr()
@@ -1580,9 +2594,27 @@
 	return b, nil
 }
 
+// consumeFloatPtr wire decodes a *float32 pointer as a Float.
+func consumeFloatPtr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Float32Ptr()
+	if *vp == nil {
+		*vp = new(float32)
+	}
+	**vp = math.Float32frombits(v)
+	return n, nil
+}
+
 var coderFloatPtr = pointerCoderFuncs{
-	size:    sizeFloatPtr,
-	marshal: appendFloatPtr,
+	size:      sizeFloatPtr,
+	marshal:   appendFloatPtr,
+	unmarshal: consumeFloatPtr,
 }
 
 // sizeFloatSlice returns the size of wire encoding a []float32 pointer as a repeated Float.
@@ -1602,9 +2634,41 @@
 	return b, nil
 }
 
+// consumeFloatSlice wire decodes a []float32 pointer as a repeated Float.
+func consumeFloatSlice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Float32Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, math.Float32frombits(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, math.Float32frombits(v))
+	return n, nil
+}
+
 var coderFloatSlice = pointerCoderFuncs{
-	size:    sizeFloatSlice,
-	marshal: appendFloatSlice,
+	size:      sizeFloatSlice,
+	marshal:   appendFloatSlice,
+	unmarshal: consumeFloatSlice,
 }
 
 // sizeFloatPackedSlice returns the size of wire encoding a []float32 pointer as a packed repeated Float.
@@ -1633,8 +2697,9 @@
 }
 
 var coderFloatPackedSlice = pointerCoderFuncs{
-	size:    sizeFloatPackedSlice,
-	marshal: appendFloatPackedSlice,
+	size:      sizeFloatPackedSlice,
+	marshal:   appendFloatPackedSlice,
+	unmarshal: consumeFloatSlice,
 }
 
 // sizeFloatIface returns the size of wire encoding a float32 value as a Float.
@@ -1650,9 +2715,22 @@
 	return b, nil
 }
 
+// consumeFloatIface decodes a float32 value as a Float.
+func consumeFloatIface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return math.Float32frombits(v), n, nil
+}
+
 var coderFloatIface = ifaceCoderFuncs{
-	size:    sizeFloatIface,
-	marshal: appendFloatIface,
+	size:      sizeFloatIface,
+	marshal:   appendFloatIface,
+	unmarshal: consumeFloatIface,
 }
 
 // sizeFloatSliceIface returns the size of wire encoding a []float32 value as a repeated Float.
@@ -1672,9 +2750,41 @@
 	return b, nil
 }
 
+// consumeFloatSliceIface wire decodes a []float32 value as a repeated Float.
+func consumeFloatSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]float32)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed32(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, math.Float32frombits(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed32Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed32(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, math.Float32frombits(v))
+	return ival, n, nil
+}
+
 var coderFloatSliceIface = ifaceCoderFuncs{
-	size:    sizeFloatSliceIface,
-	marshal: appendFloatSliceIface,
+	size:      sizeFloatSliceIface,
+	marshal:   appendFloatSliceIface,
+	unmarshal: consumeFloatSliceIface,
 }
 
 // sizeSfixed64 returns the size of wire encoding a int64 pointer as a Sfixed64.
@@ -1691,9 +2801,23 @@
 	return b, nil
 }
 
+// consumeSfixed64 wire decodes a int64 pointer as a Sfixed64.
+func consumeSfixed64(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Int64() = int64(v)
+	return n, nil
+}
+
 var coderSfixed64 = pointerCoderFuncs{
-	size:    sizeSfixed64,
-	marshal: appendSfixed64,
+	size:      sizeSfixed64,
+	marshal:   appendSfixed64,
+	unmarshal: consumeSfixed64,
 }
 
 // sizeSfixed64 returns the size of wire encoding a int64 pointer as a Sfixed64.
@@ -1719,8 +2843,9 @@
 }
 
 var coderSfixed64NoZero = pointerCoderFuncs{
-	size:    sizeSfixed64NoZero,
-	marshal: appendSfixed64NoZero,
+	size:      sizeSfixed64NoZero,
+	marshal:   appendSfixed64NoZero,
+	unmarshal: consumeSfixed64,
 }
 
 // sizeSfixed64Ptr returns the size of wire encoding a *int64 pointer as a Sfixed64.
@@ -1729,7 +2854,7 @@
 	return tagsize + wire.SizeFixed64()
 }
 
-// appendSfixed64 wire encodes a *int64 pointer as a Sfixed64.
+// appendSfixed64Ptr wire encodes a *int64 pointer as a Sfixed64.
 // It panics if the pointer is nil.
 func appendSfixed64Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Int64Ptr()
@@ -1738,9 +2863,27 @@
 	return b, nil
 }
 
+// consumeSfixed64Ptr wire decodes a *int64 pointer as a Sfixed64.
+func consumeSfixed64Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Int64Ptr()
+	if *vp == nil {
+		*vp = new(int64)
+	}
+	**vp = int64(v)
+	return n, nil
+}
+
 var coderSfixed64Ptr = pointerCoderFuncs{
-	size:    sizeSfixed64Ptr,
-	marshal: appendSfixed64Ptr,
+	size:      sizeSfixed64Ptr,
+	marshal:   appendSfixed64Ptr,
+	unmarshal: consumeSfixed64Ptr,
 }
 
 // sizeSfixed64Slice returns the size of wire encoding a []int64 pointer as a repeated Sfixed64.
@@ -1760,9 +2903,41 @@
 	return b, nil
 }
 
+// consumeSfixed64Slice wire decodes a []int64 pointer as a repeated Sfixed64.
+func consumeSfixed64Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Int64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, int64(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int64(v))
+	return n, nil
+}
+
 var coderSfixed64Slice = pointerCoderFuncs{
-	size:    sizeSfixed64Slice,
-	marshal: appendSfixed64Slice,
+	size:      sizeSfixed64Slice,
+	marshal:   appendSfixed64Slice,
+	unmarshal: consumeSfixed64Slice,
 }
 
 // sizeSfixed64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sfixed64.
@@ -1791,8 +2966,9 @@
 }
 
 var coderSfixed64PackedSlice = pointerCoderFuncs{
-	size:    sizeSfixed64PackedSlice,
-	marshal: appendSfixed64PackedSlice,
+	size:      sizeSfixed64PackedSlice,
+	marshal:   appendSfixed64PackedSlice,
+	unmarshal: consumeSfixed64Slice,
 }
 
 // sizeSfixed64Iface returns the size of wire encoding a int64 value as a Sfixed64.
@@ -1808,9 +2984,22 @@
 	return b, nil
 }
 
+// consumeSfixed64Iface decodes a int64 value as a Sfixed64.
+func consumeSfixed64Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return int64(v), n, nil
+}
+
 var coderSfixed64Iface = ifaceCoderFuncs{
-	size:    sizeSfixed64Iface,
-	marshal: appendSfixed64Iface,
+	size:      sizeSfixed64Iface,
+	marshal:   appendSfixed64Iface,
+	unmarshal: consumeSfixed64Iface,
 }
 
 // sizeSfixed64SliceIface returns the size of wire encoding a []int64 value as a repeated Sfixed64.
@@ -1830,9 +3019,41 @@
 	return b, nil
 }
 
+// consumeSfixed64SliceIface wire decodes a []int64 value as a repeated Sfixed64.
+func consumeSfixed64SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]int64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, int64(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, int64(v))
+	return ival, n, nil
+}
+
 var coderSfixed64SliceIface = ifaceCoderFuncs{
-	size:    sizeSfixed64SliceIface,
-	marshal: appendSfixed64SliceIface,
+	size:      sizeSfixed64SliceIface,
+	marshal:   appendSfixed64SliceIface,
+	unmarshal: consumeSfixed64SliceIface,
 }
 
 // sizeFixed64 returns the size of wire encoding a uint64 pointer as a Fixed64.
@@ -1849,9 +3070,23 @@
 	return b, nil
 }
 
+// consumeFixed64 wire decodes a uint64 pointer as a Fixed64.
+func consumeFixed64(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Uint64() = v
+	return n, nil
+}
+
 var coderFixed64 = pointerCoderFuncs{
-	size:    sizeFixed64,
-	marshal: appendFixed64,
+	size:      sizeFixed64,
+	marshal:   appendFixed64,
+	unmarshal: consumeFixed64,
 }
 
 // sizeFixed64 returns the size of wire encoding a uint64 pointer as a Fixed64.
@@ -1877,8 +3112,9 @@
 }
 
 var coderFixed64NoZero = pointerCoderFuncs{
-	size:    sizeFixed64NoZero,
-	marshal: appendFixed64NoZero,
+	size:      sizeFixed64NoZero,
+	marshal:   appendFixed64NoZero,
+	unmarshal: consumeFixed64,
 }
 
 // sizeFixed64Ptr returns the size of wire encoding a *uint64 pointer as a Fixed64.
@@ -1887,7 +3123,7 @@
 	return tagsize + wire.SizeFixed64()
 }
 
-// appendFixed64 wire encodes a *uint64 pointer as a Fixed64.
+// appendFixed64Ptr wire encodes a *uint64 pointer as a Fixed64.
 // It panics if the pointer is nil.
 func appendFixed64Ptr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Uint64Ptr()
@@ -1896,9 +3132,27 @@
 	return b, nil
 }
 
+// consumeFixed64Ptr wire decodes a *uint64 pointer as a Fixed64.
+func consumeFixed64Ptr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Uint64Ptr()
+	if *vp == nil {
+		*vp = new(uint64)
+	}
+	**vp = v
+	return n, nil
+}
+
 var coderFixed64Ptr = pointerCoderFuncs{
-	size:    sizeFixed64Ptr,
-	marshal: appendFixed64Ptr,
+	size:      sizeFixed64Ptr,
+	marshal:   appendFixed64Ptr,
+	unmarshal: consumeFixed64Ptr,
 }
 
 // sizeFixed64Slice returns the size of wire encoding a []uint64 pointer as a repeated Fixed64.
@@ -1918,9 +3172,41 @@
 	return b, nil
 }
 
+// consumeFixed64Slice wire decodes a []uint64 pointer as a repeated Fixed64.
+func consumeFixed64Slice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Uint64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return n, nil
+}
+
 var coderFixed64Slice = pointerCoderFuncs{
-	size:    sizeFixed64Slice,
-	marshal: appendFixed64Slice,
+	size:      sizeFixed64Slice,
+	marshal:   appendFixed64Slice,
+	unmarshal: consumeFixed64Slice,
 }
 
 // sizeFixed64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Fixed64.
@@ -1949,8 +3235,9 @@
 }
 
 var coderFixed64PackedSlice = pointerCoderFuncs{
-	size:    sizeFixed64PackedSlice,
-	marshal: appendFixed64PackedSlice,
+	size:      sizeFixed64PackedSlice,
+	marshal:   appendFixed64PackedSlice,
+	unmarshal: consumeFixed64Slice,
 }
 
 // sizeFixed64Iface returns the size of wire encoding a uint64 value as a Fixed64.
@@ -1966,9 +3253,22 @@
 	return b, nil
 }
 
+// consumeFixed64Iface decodes a uint64 value as a Fixed64.
+func consumeFixed64Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return v, n, nil
+}
+
 var coderFixed64Iface = ifaceCoderFuncs{
-	size:    sizeFixed64Iface,
-	marshal: appendFixed64Iface,
+	size:      sizeFixed64Iface,
+	marshal:   appendFixed64Iface,
+	unmarshal: consumeFixed64Iface,
 }
 
 // sizeFixed64SliceIface returns the size of wire encoding a []uint64 value as a repeated Fixed64.
@@ -1988,9 +3288,41 @@
 	return b, nil
 }
 
+// consumeFixed64SliceIface wire decodes a []uint64 value as a repeated Fixed64.
+func consumeFixed64SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]uint64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, v)
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return ival, n, nil
+}
+
 var coderFixed64SliceIface = ifaceCoderFuncs{
-	size:    sizeFixed64SliceIface,
-	marshal: appendFixed64SliceIface,
+	size:      sizeFixed64SliceIface,
+	marshal:   appendFixed64SliceIface,
+	unmarshal: consumeFixed64SliceIface,
 }
 
 // sizeDouble returns the size of wire encoding a float64 pointer as a Double.
@@ -2007,9 +3339,23 @@
 	return b, nil
 }
 
+// consumeDouble wire decodes a float64 pointer as a Double.
+func consumeDouble(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Float64() = math.Float64frombits(v)
+	return n, nil
+}
+
 var coderDouble = pointerCoderFuncs{
-	size:    sizeDouble,
-	marshal: appendDouble,
+	size:      sizeDouble,
+	marshal:   appendDouble,
+	unmarshal: consumeDouble,
 }
 
 // sizeDouble returns the size of wire encoding a float64 pointer as a Double.
@@ -2035,8 +3381,9 @@
 }
 
 var coderDoubleNoZero = pointerCoderFuncs{
-	size:    sizeDoubleNoZero,
-	marshal: appendDoubleNoZero,
+	size:      sizeDoubleNoZero,
+	marshal:   appendDoubleNoZero,
+	unmarshal: consumeDouble,
 }
 
 // sizeDoublePtr returns the size of wire encoding a *float64 pointer as a Double.
@@ -2045,7 +3392,7 @@
 	return tagsize + wire.SizeFixed64()
 }
 
-// appendDouble wire encodes a *float64 pointer as a Double.
+// appendDoublePtr wire encodes a *float64 pointer as a Double.
 // It panics if the pointer is nil.
 func appendDoublePtr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.Float64Ptr()
@@ -2054,9 +3401,27 @@
 	return b, nil
 }
 
+// consumeDoublePtr wire decodes a *float64 pointer as a Double.
+func consumeDoublePtr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.Float64Ptr()
+	if *vp == nil {
+		*vp = new(float64)
+	}
+	**vp = math.Float64frombits(v)
+	return n, nil
+}
+
 var coderDoublePtr = pointerCoderFuncs{
-	size:    sizeDoublePtr,
-	marshal: appendDoublePtr,
+	size:      sizeDoublePtr,
+	marshal:   appendDoublePtr,
+	unmarshal: consumeDoublePtr,
 }
 
 // sizeDoubleSlice returns the size of wire encoding a []float64 pointer as a repeated Double.
@@ -2076,9 +3441,41 @@
 	return b, nil
 }
 
+// consumeDoubleSlice wire decodes a []float64 pointer as a repeated Double.
+func consumeDoubleSlice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.Float64Slice()
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			s = append(s, math.Float64frombits(v))
+			b = b[n:]
+		}
+		*sp = s
+		return n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, math.Float64frombits(v))
+	return n, nil
+}
+
 var coderDoubleSlice = pointerCoderFuncs{
-	size:    sizeDoubleSlice,
-	marshal: appendDoubleSlice,
+	size:      sizeDoubleSlice,
+	marshal:   appendDoubleSlice,
+	unmarshal: consumeDoubleSlice,
 }
 
 // sizeDoublePackedSlice returns the size of wire encoding a []float64 pointer as a packed repeated Double.
@@ -2107,8 +3504,9 @@
 }
 
 var coderDoublePackedSlice = pointerCoderFuncs{
-	size:    sizeDoublePackedSlice,
-	marshal: appendDoublePackedSlice,
+	size:      sizeDoublePackedSlice,
+	marshal:   appendDoublePackedSlice,
+	unmarshal: consumeDoubleSlice,
 }
 
 // sizeDoubleIface returns the size of wire encoding a float64 value as a Double.
@@ -2124,9 +3522,22 @@
 	return b, nil
 }
 
+// consumeDoubleIface decodes a float64 value as a Double.
+func consumeDoubleIface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return math.Float64frombits(v), n, nil
+}
+
 var coderDoubleIface = ifaceCoderFuncs{
-	size:    sizeDoubleIface,
-	marshal: appendDoubleIface,
+	size:      sizeDoubleIface,
+	marshal:   appendDoubleIface,
+	unmarshal: consumeDoubleIface,
 }
 
 // sizeDoubleSliceIface returns the size of wire encoding a []float64 value as a repeated Double.
@@ -2146,9 +3557,41 @@
 	return b, nil
 }
 
+// consumeDoubleSliceIface wire decodes a []float64 value as a repeated Double.
+func consumeDoubleSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]float64)
+	if wtyp == wire.BytesType {
+		s := *sp
+		b, n = wire.ConsumeBytes(b)
+		if n < 0 {
+			return nil, 0, wire.ParseError(n)
+		}
+		for len(b) > 0 {
+			v, n := wire.ConsumeFixed64(b)
+			if n < 0 {
+				return nil, 0, wire.ParseError(n)
+			}
+			s = append(s, math.Float64frombits(v))
+			b = b[n:]
+		}
+		*sp = s
+		return ival, n, nil
+	}
+	if wtyp != wire.Fixed64Type {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeFixed64(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, math.Float64frombits(v))
+	return ival, n, nil
+}
+
 var coderDoubleSliceIface = ifaceCoderFuncs{
-	size:    sizeDoubleSliceIface,
-	marshal: appendDoubleSliceIface,
+	size:      sizeDoubleSliceIface,
+	marshal:   appendDoubleSliceIface,
+	unmarshal: consumeDoubleSliceIface,
 }
 
 // sizeString returns the size of wire encoding a string pointer as a String.
@@ -2165,9 +3608,23 @@
 	return b, nil
 }
 
+// consumeString wire decodes a string pointer as a String.
+func consumeString(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.String() = v
+	return n, nil
+}
+
 var coderString = pointerCoderFuncs{
-	size:    sizeString,
-	marshal: appendString,
+	size:      sizeString,
+	marshal:   appendString,
+	unmarshal: consumeString,
 }
 
 // sizeString returns the size of wire encoding a string pointer as a String.
@@ -2193,8 +3650,9 @@
 }
 
 var coderStringNoZero = pointerCoderFuncs{
-	size:    sizeStringNoZero,
-	marshal: appendStringNoZero,
+	size:      sizeStringNoZero,
+	marshal:   appendStringNoZero,
+	unmarshal: consumeString,
 }
 
 // sizeStringPtr returns the size of wire encoding a *string pointer as a String.
@@ -2204,7 +3662,7 @@
 	return tagsize + wire.SizeBytes(len(v))
 }
 
-// appendString wire encodes a *string pointer as a String.
+// appendStringPtr wire encodes a *string pointer as a String.
 // It panics if the pointer is nil.
 func appendStringPtr(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
 	v := **p.StringPtr()
@@ -2213,9 +3671,27 @@
 	return b, nil
 }
 
+// consumeStringPtr wire decodes a *string pointer as a String.
+func consumeStringPtr(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	vp := p.StringPtr()
+	if *vp == nil {
+		*vp = new(string)
+	}
+	**vp = v
+	return n, nil
+}
+
 var coderStringPtr = pointerCoderFuncs{
-	size:    sizeStringPtr,
-	marshal: appendStringPtr,
+	size:      sizeStringPtr,
+	marshal:   appendStringPtr,
+	unmarshal: consumeStringPtr,
 }
 
 // sizeStringSlice returns the size of wire encoding a []string pointer as a repeated String.
@@ -2237,9 +3713,24 @@
 	return b, nil
 }
 
+// consumeStringSlice wire decodes a []string pointer as a repeated String.
+func consumeStringSlice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.StringSlice()
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return n, nil
+}
+
 var coderStringSlice = pointerCoderFuncs{
-	size:    sizeStringSlice,
-	marshal: appendStringSlice,
+	size:      sizeStringSlice,
+	marshal:   appendStringSlice,
+	unmarshal: consumeStringSlice,
 }
 
 // sizeStringIface returns the size of wire encoding a string value as a String.
@@ -2256,9 +3747,22 @@
 	return b, nil
 }
 
+// consumeStringIface decodes a string value as a String.
+func consumeStringIface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.BytesType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return v, n, nil
+}
+
 var coderStringIface = ifaceCoderFuncs{
-	size:    sizeStringIface,
-	marshal: appendStringIface,
+	size:      sizeStringIface,
+	marshal:   appendStringIface,
+	unmarshal: consumeStringIface,
 }
 
 // sizeStringSliceIface returns the size of wire encoding a []string value as a repeated String.
@@ -2280,9 +3784,24 @@
 	return b, nil
 }
 
+// consumeStringSliceIface wire decodes a []string value as a repeated String.
+func consumeStringSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[]string)
+	if wtyp != wire.BytesType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeString(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, v)
+	return ival, n, nil
+}
+
 var coderStringSliceIface = ifaceCoderFuncs{
-	size:    sizeStringSliceIface,
-	marshal: appendStringSliceIface,
+	size:      sizeStringSliceIface,
+	marshal:   appendStringSliceIface,
+	unmarshal: consumeStringSliceIface,
 }
 
 // sizeBytes returns the size of wire encoding a []byte pointer as a Bytes.
@@ -2299,9 +3818,23 @@
 	return b, nil
 }
 
+// consumeBytes wire decodes a []byte pointer as a Bytes.
+func consumeBytes(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*p.Bytes() = append(([]byte)(nil), v...)
+	return n, nil
+}
+
 var coderBytes = pointerCoderFuncs{
-	size:    sizeBytes,
-	marshal: appendBytes,
+	size:      sizeBytes,
+	marshal:   appendBytes,
+	unmarshal: consumeBytes,
 }
 
 // sizeBytes returns the size of wire encoding a []byte pointer as a Bytes.
@@ -2327,8 +3860,9 @@
 }
 
 var coderBytesNoZero = pointerCoderFuncs{
-	size:    sizeBytesNoZero,
-	marshal: appendBytesNoZero,
+	size:      sizeBytesNoZero,
+	marshal:   appendBytesNoZero,
+	unmarshal: consumeBytes,
 }
 
 // sizeBytesSlice returns the size of wire encoding a [][]byte pointer as a repeated Bytes.
@@ -2350,9 +3884,24 @@
 	return b, nil
 }
 
+// consumeBytesSlice wire decodes a [][]byte pointer as a repeated Bytes.
+func consumeBytesSlice(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	sp := p.BytesSlice()
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, append(([]byte)(nil), v...))
+	return n, nil
+}
+
 var coderBytesSlice = pointerCoderFuncs{
-	size:    sizeBytesSlice,
-	marshal: appendBytesSlice,
+	size:      sizeBytesSlice,
+	marshal:   appendBytesSlice,
+	unmarshal: consumeBytesSlice,
 }
 
 // sizeBytesIface returns the size of wire encoding a []byte value as a Bytes.
@@ -2369,9 +3918,22 @@
 	return b, nil
 }
 
+// consumeBytesIface decodes a []byte value as a Bytes.
+func consumeBytesIface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
+	if wtyp != wire.BytesType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	return append(([]byte)(nil), v...), n, nil
+}
+
 var coderBytesIface = ifaceCoderFuncs{
-	size:    sizeBytesIface,
-	marshal: appendBytesIface,
+	size:      sizeBytesIface,
+	marshal:   appendBytesIface,
+	unmarshal: consumeBytesIface,
 }
 
 // sizeBytesSliceIface returns the size of wire encoding a [][]byte value as a repeated Bytes.
@@ -2393,9 +3955,24 @@
 	return b, nil
 }
 
+// consumeBytesSliceIface wire decodes a [][]byte value as a repeated Bytes.
+func consumeBytesSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
+	sp := ival.(*[][]byte)
+	if wtyp != wire.BytesType {
+		return nil, 0, errUnknown
+	}
+	v, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return nil, 0, wire.ParseError(n)
+	}
+	*sp = append(*sp, append(([]byte)(nil), v...))
+	return ival, n, nil
+}
+
 var coderBytesSliceIface = ifaceCoderFuncs{
-	size:    sizeBytesSliceIface,
-	marshal: appendBytesSliceIface,
+	size:      sizeBytesSliceIface,
+	marshal:   appendBytesSliceIface,
+	unmarshal: consumeBytesSliceIface,
 }
 
 var wireTypes = map[protoreflect.Kind]wire.Type{
diff --git a/internal/impl/codec_map.go b/internal/impl/codec_map.go
index 5a02c34..53a860b 100644
--- a/internal/impl/codec_map.go
+++ b/internal/impl/codec_map.go
@@ -16,6 +16,17 @@
 
 var protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
 
+type mapInfo struct {
+	goType     reflect.Type
+	keyWiretag uint64
+	valWiretag uint64
+	keyFuncs   ifaceCoderFuncs
+	valFuncs   ifaceCoderFuncs
+	keyZero    interface{}
+	valZero    interface{}
+	newVal     func() interface{}
+}
+
 func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointerCoderFuncs) {
 	// TODO: Consider generating specialized map coders.
 	keyField := fd.MapKey()
@@ -25,6 +36,22 @@
 	keyFuncs := encoderFuncsForValue(keyField, ft.Key())
 	valFuncs := encoderFuncsForValue(valField, ft.Elem())
 
+	mapi := &mapInfo{
+		goType:     ft,
+		keyWiretag: keyWiretag,
+		valWiretag: valWiretag,
+		keyFuncs:   keyFuncs,
+		valFuncs:   valFuncs,
+		keyZero:    reflect.Zero(ft.Key()).Interface(),
+		valZero:    reflect.Zero(ft.Elem()).Interface(),
+	}
+	switch valField.Kind() {
+	case pref.GroupKind, pref.MessageKind:
+		mapi.newVal = func() interface{} {
+			return reflect.New(ft.Elem().Elem()).Interface()
+		}
+	}
+
 	funcs = pointerCoderFuncs{
 		size: func(p pointer, tagsize int, opts marshalOptions) int {
 			return sizeMap(p, tagsize, ft, keyFuncs, valFuncs, opts)
@@ -32,6 +59,9 @@
 		marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
 			return appendMap(b, p, wiretag, keyWiretag, valWiretag, ft, keyFuncs, valFuncs, opts)
 		},
+		unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
+			return consumeMap(b, p, wtyp, mapi, opts)
+		},
 	}
 	if valFuncs.isInit != nil {
 		funcs.isInit = func(p pointer) error {
@@ -46,6 +76,64 @@
 	mapValTagSize = 1 // field 2, tag size 2.
 )
 
+func consumeMap(b []byte, p pointer, wtyp wire.Type, mapi *mapInfo, opts unmarshalOptions) (int, error) {
+	mp := p.AsValueOf(mapi.goType)
+	if mp.Elem().IsNil() {
+		mp.Elem().Set(reflect.MakeMap(mapi.goType))
+	}
+	m := mp.Elem()
+
+	if wtyp != wire.BytesType {
+		return 0, errUnknown
+	}
+	b, n := wire.ConsumeBytes(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	var (
+		key = mapi.keyZero
+		val = mapi.valZero
+	)
+	if mapi.newVal != nil {
+		val = mapi.newVal()
+	}
+	for len(b) > 0 {
+		num, wtyp, n := wire.ConsumeTag(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		b = b[n:]
+		err := errUnknown
+		switch num {
+		case 1:
+			var v interface{}
+			v, n, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
+			if err != nil {
+				break
+			}
+			key = v
+		case 2:
+			var v interface{}
+			v, n, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
+			if err != nil {
+				break
+			}
+			val = v
+		}
+		if err == errUnknown {
+			n = wire.ConsumeFieldValue(num, wtyp, b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+		} else if err != nil {
+			return 0, err
+		}
+		b = b[n:]
+	}
+	m.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(val))
+	return n, nil
+}
+
 func sizeMap(p pointer, tagsize int, goType reflect.Type, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) int {
 	m := p.AsValueOf(goType).Elem()
 	n := 0
diff --git a/internal/impl/codec_message.go b/internal/impl/codec_message.go
index e4e3706..61c88c1 100644
--- a/internal/impl/codec_message.go
+++ b/internal/impl/codec_message.go
@@ -18,6 +18,8 @@
 // possible.
 type coderMessageInfo struct {
 	orderedCoderFields []*coderFieldInfo
+	denseCoderFields   []*coderFieldInfo
+	coderFields        map[wire.Number]*coderFieldInfo
 	sizecacheOffset    offset
 	unknownOffset      offset
 	extensionOffset    offset
@@ -39,13 +41,14 @@
 	mi.unknownOffset = si.unknownOffset
 	mi.extensionOffset = si.extensionOffset
 
+	mi.coderFields = make(map[wire.Number]*coderFieldInfo)
 	for i := 0; i < mi.PBType.Descriptor().Fields().Len(); i++ {
 		fd := mi.PBType.Descriptor().Fields().Get(i)
-		if fd.ContainingOneof() != nil {
-			continue
-		}
 
 		fs := si.fieldsByNumber[fd.Number()]
+		if fd.ContainingOneof() != nil {
+			fs = si.oneofsByName[fd.ContainingOneof().Name()]
+		}
 		ft := fs.Type
 		var wiretag uint64
 		if !fd.IsPacked() {
@@ -53,37 +56,51 @@
 		} else {
 			wiretag = wire.EncodeTag(fd.Number(), wire.BytesType)
 		}
-		mi.orderedCoderFields = append(mi.orderedCoderFields, &coderFieldInfo{
+		var funcs pointerCoderFuncs
+		if fd.ContainingOneof() != nil {
+			funcs = makeOneofFieldCoder(si, fd)
+		} else {
+			funcs = fieldCoder(fd, ft)
+		}
+		cf := &coderFieldInfo{
 			num:     fd.Number(),
 			offset:  offsetOf(fs, mi.Exporter),
 			wiretag: wiretag,
 			tagsize: wire.SizeVarint(wiretag),
-			funcs:   fieldCoder(fd, ft),
+			funcs:   funcs,
 			isPointer: (fd.Cardinality() == pref.Repeated ||
 				fd.Kind() == pref.MessageKind ||
 				fd.Kind() == pref.GroupKind ||
 				fd.Syntax() != pref.Proto3),
 			isRequired: fd.Cardinality() == pref.Required,
-		})
-	}
-	for i := 0; i < mi.PBType.Descriptor().Oneofs().Len(); i++ {
-		od := mi.PBType.Descriptor().Oneofs().Get(i)
-		fs := si.oneofsByName[od.Name()]
-		mi.orderedCoderFields = append(mi.orderedCoderFields, &coderFieldInfo{
-			num:       od.Fields().Get(0).Number(),
-			offset:    offsetOf(fs, mi.Exporter),
-			funcs:     makeOneofFieldCoder(fs, od, si.fieldsByNumber, si.oneofWrappersByNumber),
-			isPointer: true,
-		})
+		}
+		mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
+		mi.coderFields[cf.num] = cf
 	}
 	sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
 		return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
 	})
 
+	var maxDense pref.FieldNumber
+	for _, cf := range mi.orderedCoderFields {
+		if cf.num >= 16 && cf.num >= 2*maxDense {
+			break
+		}
+		maxDense = cf.num
+	}
+	mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
+	for _, cf := range mi.orderedCoderFields {
+		if int(cf.num) > len(mi.denseCoderFields) {
+			break
+		}
+		mi.denseCoderFields[cf.num] = cf
+	}
+
 	mi.needsInitCheck = needsInitCheck(mi.PBType)
 	mi.methods = piface.Methods{
 		Flags:         piface.MethodFlagDeterministicMarshal,
 		MarshalAppend: mi.marshalAppend,
+		Unmarshal:     mi.unmarshal,
 		Size:          mi.size,
 		IsInitialized: mi.isInitialized,
 	}
diff --git a/internal/impl/codec_reflect.go b/internal/impl/codec_reflect.go
index 05ceb33..d307efe 100644
--- a/internal/impl/codec_reflect.go
+++ b/internal/impl/codec_reflect.go
@@ -7,6 +7,8 @@
 package impl
 
 import (
+	"reflect"
+
 	"google.golang.org/protobuf/internal/encoding/wire"
 )
 
@@ -22,9 +24,22 @@
 	return b, nil
 }
 
+func consumeEnum(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	v, n := wire.ConsumeVarint(b)
+	if n < 0 {
+		return 0, wire.ParseError(n)
+	}
+	p.v.Elem().SetInt(int64(v))
+	return n, nil
+}
+
 var coderEnum = pointerCoderFuncs{
-	size:    sizeEnum,
-	marshal: appendEnum,
+	size:      sizeEnum,
+	marshal:   appendEnum,
+	unmarshal: consumeEnum,
 }
 
 func sizeEnumNoZero(p pointer, tagsize int, opts marshalOptions) (size int) {
@@ -42,8 +57,9 @@
 }
 
 var coderEnumNoZero = pointerCoderFuncs{
-	size:    sizeEnumNoZero,
-	marshal: appendEnumNoZero,
+	size:      sizeEnumNoZero,
+	marshal:   appendEnumNoZero,
+	unmarshal: consumeEnum,
 }
 
 func sizeEnumPtr(p pointer, tagsize int, opts marshalOptions) (size int) {
@@ -54,9 +70,20 @@
 	return appendEnum(b, pointer{p.v.Elem()}, wiretag, opts)
 }
 
+func consumeEnumPtr(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (n int, err error) {
+	if wtyp != wire.VarintType {
+		return 0, errUnknown
+	}
+	if p.v.Elem().IsNil() {
+		p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem()))
+	}
+	return consumeEnum(b, pointer{p.v.Elem()}, wtyp, opts)
+}
+
 var coderEnumPtr = pointerCoderFuncs{
-	size:    sizeEnumPtr,
-	marshal: appendEnumPtr,
+	size:      sizeEnumPtr,
+	marshal:   appendEnumPtr,
+	unmarshal: consumeEnumPtr,
 }
 
 func sizeEnumSlice(p pointer, tagsize int, opts marshalOptions) (size int) {
@@ -67,9 +94,14 @@
 	return appendEnumSliceReflect(b, p.v.Elem(), wiretag, opts)
 }
 
+func consumeEnumSlice(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (n int, err error) {
+	return consumeEnumSliceReflect(b, p.v, wtyp, opts)
+}
+
 var coderEnumSlice = pointerCoderFuncs{
-	size:    sizeEnumSlice,
-	marshal: appendEnumSlice,
+	size:      sizeEnumSlice,
+	marshal:   appendEnumSlice,
+	unmarshal: consumeEnumSlice,
 }
 
 func sizeEnumPackedSlice(p pointer, tagsize int, _ marshalOptions) (size int) {
@@ -104,6 +136,7 @@
 }
 
 var coderEnumPackedSlice = pointerCoderFuncs{
-	size:    sizeEnumPackedSlice,
-	marshal: appendEnumPackedSlice,
+	size:      sizeEnumPackedSlice,
+	marshal:   appendEnumPackedSlice,
+	unmarshal: consumeEnumSlice,
 }
diff --git a/internal/impl/codec_tables.go b/internal/impl/codec_tables.go
index 8acb10d..3d492af 100644
--- a/internal/impl/codec_tables.go
+++ b/internal/impl/codec_tables.go
@@ -8,21 +8,24 @@
 	"fmt"
 	"reflect"
 
+	"google.golang.org/protobuf/internal/encoding/wire"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 )
 
 // pointerCoderFuncs is a set of pointer encoding functions.
 type pointerCoderFuncs struct {
-	size    func(p pointer, tagsize int, opts marshalOptions) int
-	marshal func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
-	isInit  func(p pointer) error
+	size      func(p pointer, tagsize int, opts marshalOptions) int
+	marshal   func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
+	unmarshal func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error)
+	isInit    func(p pointer) error
 }
 
 // ifaceCoderFuncs is a set of interface{} encoding functions.
 type ifaceCoderFuncs struct {
-	size    func(ival interface{}, tagsize int, opts marshalOptions) int
-	marshal func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
-	isInit  func(ival interface{}) error
+	size      func(ival interface{}, tagsize int, opts marshalOptions) int
+	marshal   func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
+	unmarshal func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error)
+	isInit    func(ival interface{}) error
 }
 
 // fieldCoder returns pointer functions for a field, used for operating on
@@ -574,7 +577,7 @@
 		case pref.MessageKind:
 			return coderMessageIface
 		case pref.GroupKind:
-			return coderGroupIface
+			return makeGroupValueCoder(fd, ft)
 		}
 	}
 	panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))
diff --git a/internal/impl/decode.go b/internal/impl/decode.go
new file mode 100644
index 0000000..5fdffe3
--- /dev/null
+++ b/internal/impl/decode.go
@@ -0,0 +1,162 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package impl
+
+import (
+	"google.golang.org/protobuf/internal/encoding/wire"
+	"google.golang.org/protobuf/internal/errors"
+	"google.golang.org/protobuf/proto"
+	pref "google.golang.org/protobuf/reflect/protoreflect"
+	preg "google.golang.org/protobuf/reflect/protoregistry"
+	piface "google.golang.org/protobuf/runtime/protoiface"
+)
+
+// unmarshalOptions is a more efficient representation of UnmarshalOptions.
+//
+// We don't preserve the AllowPartial flag, because fast-path (un)marshal
+// operations always allow partial messages.
+type unmarshalOptions struct {
+	flags    unmarshalOptionFlags
+	resolver preg.ExtensionTypeResolver
+}
+
+type unmarshalOptionFlags uint8
+
+const (
+	unmarshalDiscardUnknown unmarshalOptionFlags = 1 << iota
+)
+
+func newUnmarshalOptions(opts piface.UnmarshalOptions) unmarshalOptions {
+	o := unmarshalOptions{
+		resolver: opts.Resolver,
+	}
+	if opts.DiscardUnknown {
+		o.flags |= unmarshalDiscardUnknown
+	}
+	return o
+}
+
+func (o unmarshalOptions) Options() proto.UnmarshalOptions {
+	return proto.UnmarshalOptions{
+		AllowPartial:   true,
+		DiscardUnknown: o.DiscardUnknown(),
+		Resolver:       o.Resolver(),
+	}
+}
+
+func (o unmarshalOptions) DiscardUnknown() bool                 { return o.flags&unmarshalDiscardUnknown != 0 }
+func (o unmarshalOptions) Resolver() preg.ExtensionTypeResolver { return o.resolver }
+
+// unmarshal is protoreflect.Methods.Unmarshal.
+func (mi *MessageInfo) unmarshal(b []byte, m pref.ProtoMessage, opts piface.UnmarshalOptions) error {
+	_, err := mi.unmarshalPointer(b, pointerOfIface(m), 0, newUnmarshalOptions(opts))
+	return err
+}
+
+// errUnknown is returned during unmarshaling to indicate a parse error that
+// should result in a field being placed in the unknown fields section (for example,
+// when the wire type doesn't match) as opposed to the entire unmarshal operation
+// failing (for example, when a field extends past the available input).
+//
+// This is a sentinel error which should never be visible to the user.
+var errUnknown = errors.New("unknown")
+
+func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (int, error) {
+	mi.init()
+	var exts *map[int32]ExtensionField
+	start := len(b)
+	for len(b) > 0 {
+		// Parse the tag (field number and wire type).
+		// TODO: inline 1 and 2 byte variants?
+		num, wtyp, n := wire.ConsumeTag(b)
+		if n < 0 {
+			return 0, wire.ParseError(n)
+		}
+		b = b[n:]
+
+		var f *coderFieldInfo
+		if int(num) < len(mi.denseCoderFields) {
+			f = mi.denseCoderFields[num]
+		} else {
+			f = mi.coderFields[num]
+		}
+		err := errUnknown
+		switch {
+		case f != nil:
+			if f.funcs.unmarshal == nil {
+				break
+			}
+			n, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
+		case num == groupTag && wtyp == wire.EndGroupType:
+			// End of group.
+			return start - len(b), nil
+		default:
+			// Possible extension.
+			if exts == nil && mi.extensionOffset.IsValid() {
+				exts = p.Apply(mi.extensionOffset).Extensions()
+				if *exts == nil {
+					*exts = make(map[int32]ExtensionField)
+				}
+			}
+			if exts == nil {
+				break
+			}
+			n, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
+		}
+		if err != nil {
+			if err != errUnknown {
+				return 0, err
+			}
+			n = wire.ConsumeFieldValue(num, wtyp, b)
+			if n < 0 {
+				return 0, wire.ParseError(n)
+			}
+			if mi.unknownOffset.IsValid() {
+				u := p.Apply(mi.unknownOffset).Bytes()
+				*u = wire.AppendTag(*u, num, wtyp)
+				*u = append(*u, b[:n]...)
+			}
+		}
+		b = b[n:]
+	}
+	if groupTag != 0 {
+		return 0, errors.New("missing end group marker")
+	}
+	return start, nil
+}
+
+func (mi *MessageInfo) unmarshalExtension(b []byte, num wire.Number, wtyp wire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (n int, err error) {
+	x := exts[int32(num)]
+	xt := x.GetType()
+	if xt == nil {
+		var err error
+		xt, err = opts.Resolver().FindExtensionByNumber(mi.PBType.FullName(), num)
+		if err != nil {
+			if err == preg.NotFound {
+				return 0, errUnknown
+			}
+			return 0, err
+		}
+		x.SetType(xt)
+	}
+	xi := mi.extensionFieldInfo(xt)
+	if xi.funcs.unmarshal == nil {
+		return 0, errUnknown
+	}
+	ival := x.GetValue()
+	if ival == nil && xi.unmarshalNeedsValue {
+		// Create a new message, list, or map value to fill in.
+		// For enums, create a prototype value to let the unmarshal func know the
+		// concrete type.
+		ival = xt.InterfaceOf(xt.New())
+	}
+	v, n, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
+	if err != nil {
+		return 0, err
+	}
+	x.SetEagerValue(v)
+	exts[int32(num)] = x
+	return n, nil
+}
diff --git a/internal/impl/encode.go b/internal/impl/encode.go
index c258d46..bf7308a 100644
--- a/internal/impl/encode.go
+++ b/internal/impl/encode.go
@@ -13,19 +13,19 @@
 	piface "google.golang.org/protobuf/runtime/protoiface"
 )
 
+// marshalOptions is a more efficient representation of MarshalOptions.
+//
+// We don't preserve the AllowPartial flag, because fast-path (un)marshal
+// operations always allow partial messages.
 type marshalOptions uint
 
 const (
-	marshalAllowPartial marshalOptions = 1 << iota
-	marshalDeterministic
+	marshalDeterministic marshalOptions = 1 << iota
 	marshalUseCachedSize
 )
 
 func newMarshalOptions(opts piface.MarshalOptions) marshalOptions {
 	var o marshalOptions
-	if opts.AllowPartial {
-		o |= marshalAllowPartial
-	}
 	if opts.Deterministic {
 		o |= marshalDeterministic
 	}
@@ -37,13 +37,12 @@
 
 func (o marshalOptions) Options() proto.MarshalOptions {
 	return proto.MarshalOptions{
-		AllowPartial:  o.AllowPartial(),
+		AllowPartial:  true,
 		Deterministic: o.Deterministic(),
 		UseCachedSize: o.UseCachedSize(),
 	}
 }
 
-func (o marshalOptions) AllowPartial() bool  { return o&marshalAllowPartial != 0 }
 func (o marshalOptions) Deterministic() bool { return o&marshalDeterministic != 0 }
 func (o marshalOptions) UseCachedSize() bool { return o&marshalUseCachedSize != 0 }
 
diff --git a/internal/impl/message.go b/internal/impl/message.go
index e9a38c2..fe7cd37 100644
--- a/internal/impl/message.go
+++ b/internal/impl/message.go
@@ -516,6 +516,7 @@
 	return &piface.Methods{
 		Flags:         piface.MethodFlagDeterministicMarshal,
 		MarshalAppend: m.marshalAppend,
+		Unmarshal:     m.unmarshal,
 		Size:          m.size,
 		IsInitialized: m.isInitialized,
 	}
@@ -526,9 +527,13 @@
 func (m *messageIfaceWrapper) marshalAppend(b []byte, _ pref.ProtoMessage, opts piface.MarshalOptions) ([]byte, error) {
 	return m.mi.marshalAppendPointer(b, m.p, newMarshalOptions(opts))
 }
+func (m *messageIfaceWrapper) unmarshal(b []byte, _ pref.ProtoMessage, opts piface.UnmarshalOptions) error {
+	_, err := m.mi.unmarshalPointer(b, m.p, 0, newUnmarshalOptions(opts))
+	return err
+}
 func (m *messageIfaceWrapper) size(msg pref.ProtoMessage) (size int) {
 	return m.mi.sizePointer(m.p, 0)
 }
-func (m *messageIfaceWrapper) isInitialized(msg pref.ProtoMessage) error {
+func (m *messageIfaceWrapper) isInitialized(_ pref.ProtoMessage) error {
 	return m.mi.isInitializedPointer(m.p)
 }
diff --git a/internal/impl/pointer_reflect.go b/internal/impl/pointer_reflect.go
index 6060154..0a9c53e 100644
--- a/internal/impl/pointer_reflect.go
+++ b/internal/impl/pointer_reflect.go
@@ -135,3 +135,14 @@
 	}
 	return s
 }
+
+// AppendPointerSlice appends v to p, which must be a []*T.
+func (p pointer) AppendPointerSlice(v pointer) {
+	sp := p.v.Elem()
+	sp.Set(reflect.Append(sp, v.v))
+}
+
+// SetPointer sets *p to v.
+func (p pointer) SetPointer(v pointer) {
+	p.v.Elem().Set(v.v)
+}
diff --git a/internal/impl/pointer_unsafe.go b/internal/impl/pointer_unsafe.go
index bd5ab4b..ceca3b2 100644
--- a/internal/impl/pointer_unsafe.go
+++ b/internal/impl/pointer_unsafe.go
@@ -115,3 +115,13 @@
 	// message type. We load it as []pointer.
 	return *(*[]pointer)(p.p)
 }
+
+// AppendPointerSlice appends v to p, which must be a []*T.
+func (p pointer) AppendPointerSlice(v pointer) {
+	*(*[]pointer)(p.p) = append(*(*[]pointer)(p.p), v)
+}
+
+// SetPointer sets *p to v.
+func (p pointer) SetPointer(v pointer) {
+	*(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p)
+}