1
// Copyright 2019 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
10
"google.golang.org/protobuf/encoding/protowire"
11
"google.golang.org/protobuf/internal/errors"
12
"google.golang.org/protobuf/internal/flags"
13
"google.golang.org/protobuf/proto"
14
"google.golang.org/protobuf/reflect/protoreflect"
15
"google.golang.org/protobuf/reflect/protoregistry"
16
"google.golang.org/protobuf/runtime/protoiface"
19
var errDecode = errors.New("cannot parse invalid wire-format data")
20
var errRecursionDepth = errors.New("exceeded maximum recursion depth")
22
type unmarshalOptions struct {
23
flags protoiface.UnmarshalInputFlags
25
FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
26
FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
31
func (o unmarshalOptions) Options() proto.UnmarshalOptions {
32
return proto.UnmarshalOptions{
35
DiscardUnknown: o.DiscardUnknown(),
40
func (o unmarshalOptions) DiscardUnknown() bool {
41
return o.flags&protoiface.UnmarshalDiscardUnknown != 0
44
func (o unmarshalOptions) IsDefault() bool {
45
return o.flags == 0 && o.resolver == protoregistry.GlobalTypes
48
var lazyUnmarshalOptions = unmarshalOptions{
49
resolver: protoregistry.GlobalTypes,
50
depth: protowire.DefaultRecursionLimit,
53
type unmarshalOutput struct {
54
n int // number of bytes consumed
58
// unmarshal is protoreflect.Methods.Unmarshal.
59
func (mi *MessageInfo) unmarshal(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) {
61
if ms, ok := in.Message.(*messageState); ok {
64
p = in.Message.(*messageReflectWrapper).pointer()
66
out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions{
68
resolver: in.Resolver,
71
var flags protoiface.UnmarshalOutputFlags
73
flags |= protoiface.UnmarshalInitialized
75
return protoiface.UnmarshalOutput{
80
// errUnknown is returned during unmarshaling to indicate a parse error that
81
// should result in a field being placed in the unknown fields section (for example,
82
// when the wire type doesn't match) as opposed to the entire unmarshal operation
83
// failing (for example, when a field extends past the available input).
85
// This is a sentinel error which should never be visible to the user.
86
var errUnknown = errors.New("unknown")
88
func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
92
return out, errRecursionDepth
94
if flags.ProtoLegacy && mi.isMessageSet {
95
return unmarshalMessageSet(mi, b, p, opts)
98
var requiredMask uint64
99
var exts *map[int32]ExtensionField
102
// Parse the tag (field number and wire type).
107
} else if len(b) >= 2 && b[1] < 128 {
108
tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
112
tag, n = protowire.ConsumeVarint(b)
114
return out, errDecode
118
var num protowire.Number
119
if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) {
120
return out, errDecode
122
num = protowire.Number(n)
124
wtyp := protowire.Type(tag & 7)
126
if wtyp == protowire.EndGroupType {
128
return out, errDecode
134
var f *coderFieldInfo
135
if int(num) < len(mi.denseCoderFields) {
136
f = mi.denseCoderFields[num]
138
f = mi.coderFields[num]
144
if f.funcs.unmarshal == nil {
147
var o unmarshalOutput
148
o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, f, opts)
153
requiredMask |= f.validation.requiredBit
154
if f.funcs.isInit != nil && !o.initialized {
158
// Possible extension.
159
if exts == nil && mi.extensionOffset.IsValid() {
160
exts = p.Apply(mi.extensionOffset).Extensions()
162
*exts = make(map[int32]ExtensionField)
168
var o unmarshalOutput
169
o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
179
if err != errUnknown {
182
n = protowire.ConsumeFieldValue(num, wtyp, b)
184
return out, errDecode
186
if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() {
187
u := mi.mutableUnknownBytes(p)
188
*u = protowire.AppendTag(*u, num, wtyp)
189
*u = append(*u, b[:n]...)
195
return out, errDecode
197
if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
201
out.initialized = true
203
out.n = start - len(b)
207
func (mi *MessageInfo) unmarshalExtension(b []byte, num protowire.Number, wtyp protowire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (out unmarshalOutput, err error) {
208
x := exts[int32(num)]
212
xt, err = opts.resolver.FindExtensionByNumber(mi.Desc.FullName(), num)
214
if err == protoregistry.NotFound {
215
return out, errUnknown
217
return out, errors.New("%v: unable to resolve extension %v: %v", mi.Desc.FullName(), num, err)
220
xi := getExtensionFieldInfo(xt)
221
if xi.funcs.unmarshal == nil {
222
return out, errUnknown
224
if flags.LazyUnmarshalExtensions {
225
if opts.IsDefault() && x.canLazy(xt) {
226
out, valid := skipExtension(b, xi, num, wtyp, opts)
228
case ValidationValid:
230
x.appendLazyBytes(xt, xi, num, wtyp, b[:out.n])
234
case ValidationInvalid:
235
return out, errDecode
236
case ValidationUnknown:
241
if !ival.IsValid() && xi.unmarshalNeedsValue {
242
// Create a new message, list, or map value to fill in.
243
// For enums, create a prototype value to let the unmarshal func know the
247
v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
251
if xi.funcs.isInit == nil {
252
out.initialized = true
259
func skipExtension(b []byte, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, _ ValidationStatus) {
260
if xi.validation.mi == nil {
261
return out, ValidationUnknown
263
xi.validation.mi.init()
264
switch xi.validation.typ {
265
case validationTypeMessage:
266
if wtyp != protowire.BytesType {
267
return out, ValidationUnknown
269
v, n := protowire.ConsumeBytes(b)
271
return out, ValidationUnknown
273
out, st := xi.validation.mi.validate(v, 0, opts)
276
case validationTypeGroup:
277
if wtyp != protowire.StartGroupType {
278
return out, ValidationUnknown
280
out, st := xi.validation.mi.validate(b, num, opts)
283
return out, ValidationUnknown