xref: /aosp_15_r20/external/golang-protobuf/encoding/protojson/decode.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage protojson
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"encoding/base64"
9*1c12ee1eSDan Willemsen	"fmt"
10*1c12ee1eSDan Willemsen	"math"
11*1c12ee1eSDan Willemsen	"strconv"
12*1c12ee1eSDan Willemsen	"strings"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/json"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/messageset"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/errors"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/flags"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/genid"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/pragma"
20*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/set"
21*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/proto"
22*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
23*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
24*1c12ee1eSDan Willemsen)
25*1c12ee1eSDan Willemsen
26*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte into the given proto.Message.
27*1c12ee1eSDan Willemsen// The provided message must be mutable (e.g., a non-nil pointer to a message).
28*1c12ee1eSDan Willemsenfunc Unmarshal(b []byte, m proto.Message) error {
29*1c12ee1eSDan Willemsen	return UnmarshalOptions{}.Unmarshal(b, m)
30*1c12ee1eSDan Willemsen}
31*1c12ee1eSDan Willemsen
32*1c12ee1eSDan Willemsen// UnmarshalOptions is a configurable JSON format parser.
33*1c12ee1eSDan Willemsentype UnmarshalOptions struct {
34*1c12ee1eSDan Willemsen	pragma.NoUnkeyedLiterals
35*1c12ee1eSDan Willemsen
36*1c12ee1eSDan Willemsen	// If AllowPartial is set, input for messages that will result in missing
37*1c12ee1eSDan Willemsen	// required fields will not return an error.
38*1c12ee1eSDan Willemsen	AllowPartial bool
39*1c12ee1eSDan Willemsen
40*1c12ee1eSDan Willemsen	// If DiscardUnknown is set, unknown fields are ignored.
41*1c12ee1eSDan Willemsen	DiscardUnknown bool
42*1c12ee1eSDan Willemsen
43*1c12ee1eSDan Willemsen	// Resolver is used for looking up types when unmarshaling
44*1c12ee1eSDan Willemsen	// google.protobuf.Any messages or extension fields.
45*1c12ee1eSDan Willemsen	// If nil, this defaults to using protoregistry.GlobalTypes.
46*1c12ee1eSDan Willemsen	Resolver interface {
47*1c12ee1eSDan Willemsen		protoregistry.MessageTypeResolver
48*1c12ee1eSDan Willemsen		protoregistry.ExtensionTypeResolver
49*1c12ee1eSDan Willemsen	}
50*1c12ee1eSDan Willemsen}
51*1c12ee1eSDan Willemsen
52*1c12ee1eSDan Willemsen// Unmarshal reads the given []byte and populates the given proto.Message
53*1c12ee1eSDan Willemsen// using options in the UnmarshalOptions object.
54*1c12ee1eSDan Willemsen// It will clear the message first before setting the fields.
55*1c12ee1eSDan Willemsen// If it returns an error, the given message may be partially set.
56*1c12ee1eSDan Willemsen// The provided message must be mutable (e.g., a non-nil pointer to a message).
57*1c12ee1eSDan Willemsenfunc (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error {
58*1c12ee1eSDan Willemsen	return o.unmarshal(b, m)
59*1c12ee1eSDan Willemsen}
60*1c12ee1eSDan Willemsen
61*1c12ee1eSDan Willemsen// unmarshal is a centralized function that all unmarshal operations go through.
62*1c12ee1eSDan Willemsen// For profiling purposes, avoid changing the name of this function or
63*1c12ee1eSDan Willemsen// introducing other code paths for unmarshal that do not go through this.
64*1c12ee1eSDan Willemsenfunc (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error {
65*1c12ee1eSDan Willemsen	proto.Reset(m)
66*1c12ee1eSDan Willemsen
67*1c12ee1eSDan Willemsen	if o.Resolver == nil {
68*1c12ee1eSDan Willemsen		o.Resolver = protoregistry.GlobalTypes
69*1c12ee1eSDan Willemsen	}
70*1c12ee1eSDan Willemsen
71*1c12ee1eSDan Willemsen	dec := decoder{json.NewDecoder(b), o}
72*1c12ee1eSDan Willemsen	if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil {
73*1c12ee1eSDan Willemsen		return err
74*1c12ee1eSDan Willemsen	}
75*1c12ee1eSDan Willemsen
76*1c12ee1eSDan Willemsen	// Check for EOF.
77*1c12ee1eSDan Willemsen	tok, err := dec.Read()
78*1c12ee1eSDan Willemsen	if err != nil {
79*1c12ee1eSDan Willemsen		return err
80*1c12ee1eSDan Willemsen	}
81*1c12ee1eSDan Willemsen	if tok.Kind() != json.EOF {
82*1c12ee1eSDan Willemsen		return dec.unexpectedTokenError(tok)
83*1c12ee1eSDan Willemsen	}
84*1c12ee1eSDan Willemsen
85*1c12ee1eSDan Willemsen	if o.AllowPartial {
86*1c12ee1eSDan Willemsen		return nil
87*1c12ee1eSDan Willemsen	}
88*1c12ee1eSDan Willemsen	return proto.CheckInitialized(m)
89*1c12ee1eSDan Willemsen}
90*1c12ee1eSDan Willemsen
91*1c12ee1eSDan Willemsentype decoder struct {
92*1c12ee1eSDan Willemsen	*json.Decoder
93*1c12ee1eSDan Willemsen	opts UnmarshalOptions
94*1c12ee1eSDan Willemsen}
95*1c12ee1eSDan Willemsen
96*1c12ee1eSDan Willemsen// newError returns an error object with position info.
97*1c12ee1eSDan Willemsenfunc (d decoder) newError(pos int, f string, x ...interface{}) error {
98*1c12ee1eSDan Willemsen	line, column := d.Position(pos)
99*1c12ee1eSDan Willemsen	head := fmt.Sprintf("(line %d:%d): ", line, column)
100*1c12ee1eSDan Willemsen	return errors.New(head+f, x...)
101*1c12ee1eSDan Willemsen}
102*1c12ee1eSDan Willemsen
103*1c12ee1eSDan Willemsen// unexpectedTokenError returns a syntax error for the given unexpected token.
104*1c12ee1eSDan Willemsenfunc (d decoder) unexpectedTokenError(tok json.Token) error {
105*1c12ee1eSDan Willemsen	return d.syntaxError(tok.Pos(), "unexpected token %s", tok.RawString())
106*1c12ee1eSDan Willemsen}
107*1c12ee1eSDan Willemsen
108*1c12ee1eSDan Willemsen// syntaxError returns a syntax error for given position.
109*1c12ee1eSDan Willemsenfunc (d decoder) syntaxError(pos int, f string, x ...interface{}) error {
110*1c12ee1eSDan Willemsen	line, column := d.Position(pos)
111*1c12ee1eSDan Willemsen	head := fmt.Sprintf("syntax error (line %d:%d): ", line, column)
112*1c12ee1eSDan Willemsen	return errors.New(head+f, x...)
113*1c12ee1eSDan Willemsen}
114*1c12ee1eSDan Willemsen
115*1c12ee1eSDan Willemsen// unmarshalMessage unmarshals a message into the given protoreflect.Message.
116*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMessage(m protoreflect.Message, skipTypeURL bool) error {
117*1c12ee1eSDan Willemsen	if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil {
118*1c12ee1eSDan Willemsen		return unmarshal(d, m)
119*1c12ee1eSDan Willemsen	}
120*1c12ee1eSDan Willemsen
121*1c12ee1eSDan Willemsen	tok, err := d.Read()
122*1c12ee1eSDan Willemsen	if err != nil {
123*1c12ee1eSDan Willemsen		return err
124*1c12ee1eSDan Willemsen	}
125*1c12ee1eSDan Willemsen	if tok.Kind() != json.ObjectOpen {
126*1c12ee1eSDan Willemsen		return d.unexpectedTokenError(tok)
127*1c12ee1eSDan Willemsen	}
128*1c12ee1eSDan Willemsen
129*1c12ee1eSDan Willemsen	messageDesc := m.Descriptor()
130*1c12ee1eSDan Willemsen	if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) {
131*1c12ee1eSDan Willemsen		return errors.New("no support for proto1 MessageSets")
132*1c12ee1eSDan Willemsen	}
133*1c12ee1eSDan Willemsen
134*1c12ee1eSDan Willemsen	var seenNums set.Ints
135*1c12ee1eSDan Willemsen	var seenOneofs set.Ints
136*1c12ee1eSDan Willemsen	fieldDescs := messageDesc.Fields()
137*1c12ee1eSDan Willemsen	for {
138*1c12ee1eSDan Willemsen		// Read field name.
139*1c12ee1eSDan Willemsen		tok, err := d.Read()
140*1c12ee1eSDan Willemsen		if err != nil {
141*1c12ee1eSDan Willemsen			return err
142*1c12ee1eSDan Willemsen		}
143*1c12ee1eSDan Willemsen		switch tok.Kind() {
144*1c12ee1eSDan Willemsen		default:
145*1c12ee1eSDan Willemsen			return d.unexpectedTokenError(tok)
146*1c12ee1eSDan Willemsen		case json.ObjectClose:
147*1c12ee1eSDan Willemsen			return nil
148*1c12ee1eSDan Willemsen		case json.Name:
149*1c12ee1eSDan Willemsen			// Continue below.
150*1c12ee1eSDan Willemsen		}
151*1c12ee1eSDan Willemsen
152*1c12ee1eSDan Willemsen		name := tok.Name()
153*1c12ee1eSDan Willemsen		// Unmarshaling a non-custom embedded message in Any will contain the
154*1c12ee1eSDan Willemsen		// JSON field "@type" which should be skipped because it is not a field
155*1c12ee1eSDan Willemsen		// of the embedded message, but simply an artifact of the Any format.
156*1c12ee1eSDan Willemsen		if skipTypeURL && name == "@type" {
157*1c12ee1eSDan Willemsen			d.Read()
158*1c12ee1eSDan Willemsen			continue
159*1c12ee1eSDan Willemsen		}
160*1c12ee1eSDan Willemsen
161*1c12ee1eSDan Willemsen		// Get the FieldDescriptor.
162*1c12ee1eSDan Willemsen		var fd protoreflect.FieldDescriptor
163*1c12ee1eSDan Willemsen		if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
164*1c12ee1eSDan Willemsen			// Only extension names are in [name] format.
165*1c12ee1eSDan Willemsen			extName := protoreflect.FullName(name[1 : len(name)-1])
166*1c12ee1eSDan Willemsen			extType, err := d.opts.Resolver.FindExtensionByName(extName)
167*1c12ee1eSDan Willemsen			if err != nil && err != protoregistry.NotFound {
168*1c12ee1eSDan Willemsen				return d.newError(tok.Pos(), "unable to resolve %s: %v", tok.RawString(), err)
169*1c12ee1eSDan Willemsen			}
170*1c12ee1eSDan Willemsen			if extType != nil {
171*1c12ee1eSDan Willemsen				fd = extType.TypeDescriptor()
172*1c12ee1eSDan Willemsen				if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() {
173*1c12ee1eSDan Willemsen					return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName())
174*1c12ee1eSDan Willemsen				}
175*1c12ee1eSDan Willemsen			}
176*1c12ee1eSDan Willemsen		} else {
177*1c12ee1eSDan Willemsen			// The name can either be the JSON name or the proto field name.
178*1c12ee1eSDan Willemsen			fd = fieldDescs.ByJSONName(name)
179*1c12ee1eSDan Willemsen			if fd == nil {
180*1c12ee1eSDan Willemsen				fd = fieldDescs.ByTextName(name)
181*1c12ee1eSDan Willemsen			}
182*1c12ee1eSDan Willemsen		}
183*1c12ee1eSDan Willemsen		if flags.ProtoLegacy {
184*1c12ee1eSDan Willemsen			if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() {
185*1c12ee1eSDan Willemsen				fd = nil // reset since the weak reference is not linked in
186*1c12ee1eSDan Willemsen			}
187*1c12ee1eSDan Willemsen		}
188*1c12ee1eSDan Willemsen
189*1c12ee1eSDan Willemsen		if fd == nil {
190*1c12ee1eSDan Willemsen			// Field is unknown.
191*1c12ee1eSDan Willemsen			if d.opts.DiscardUnknown {
192*1c12ee1eSDan Willemsen				if err := d.skipJSONValue(); err != nil {
193*1c12ee1eSDan Willemsen					return err
194*1c12ee1eSDan Willemsen				}
195*1c12ee1eSDan Willemsen				continue
196*1c12ee1eSDan Willemsen			}
197*1c12ee1eSDan Willemsen			return d.newError(tok.Pos(), "unknown field %v", tok.RawString())
198*1c12ee1eSDan Willemsen		}
199*1c12ee1eSDan Willemsen
200*1c12ee1eSDan Willemsen		// Do not allow duplicate fields.
201*1c12ee1eSDan Willemsen		num := uint64(fd.Number())
202*1c12ee1eSDan Willemsen		if seenNums.Has(num) {
203*1c12ee1eSDan Willemsen			return d.newError(tok.Pos(), "duplicate field %v", tok.RawString())
204*1c12ee1eSDan Willemsen		}
205*1c12ee1eSDan Willemsen		seenNums.Set(num)
206*1c12ee1eSDan Willemsen
207*1c12ee1eSDan Willemsen		// No need to set values for JSON null unless the field type is
208*1c12ee1eSDan Willemsen		// google.protobuf.Value or google.protobuf.NullValue.
209*1c12ee1eSDan Willemsen		if tok, _ := d.Peek(); tok.Kind() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
210*1c12ee1eSDan Willemsen			d.Read()
211*1c12ee1eSDan Willemsen			continue
212*1c12ee1eSDan Willemsen		}
213*1c12ee1eSDan Willemsen
214*1c12ee1eSDan Willemsen		switch {
215*1c12ee1eSDan Willemsen		case fd.IsList():
216*1c12ee1eSDan Willemsen			list := m.Mutable(fd).List()
217*1c12ee1eSDan Willemsen			if err := d.unmarshalList(list, fd); err != nil {
218*1c12ee1eSDan Willemsen				return err
219*1c12ee1eSDan Willemsen			}
220*1c12ee1eSDan Willemsen		case fd.IsMap():
221*1c12ee1eSDan Willemsen			mmap := m.Mutable(fd).Map()
222*1c12ee1eSDan Willemsen			if err := d.unmarshalMap(mmap, fd); err != nil {
223*1c12ee1eSDan Willemsen				return err
224*1c12ee1eSDan Willemsen			}
225*1c12ee1eSDan Willemsen		default:
226*1c12ee1eSDan Willemsen			// If field is a oneof, check if it has already been set.
227*1c12ee1eSDan Willemsen			if od := fd.ContainingOneof(); od != nil {
228*1c12ee1eSDan Willemsen				idx := uint64(od.Index())
229*1c12ee1eSDan Willemsen				if seenOneofs.Has(idx) {
230*1c12ee1eSDan Willemsen					return d.newError(tok.Pos(), "error parsing %s, oneof %v is already set", tok.RawString(), od.FullName())
231*1c12ee1eSDan Willemsen				}
232*1c12ee1eSDan Willemsen				seenOneofs.Set(idx)
233*1c12ee1eSDan Willemsen			}
234*1c12ee1eSDan Willemsen
235*1c12ee1eSDan Willemsen			// Required or optional fields.
236*1c12ee1eSDan Willemsen			if err := d.unmarshalSingular(m, fd); err != nil {
237*1c12ee1eSDan Willemsen				return err
238*1c12ee1eSDan Willemsen			}
239*1c12ee1eSDan Willemsen		}
240*1c12ee1eSDan Willemsen	}
241*1c12ee1eSDan Willemsen}
242*1c12ee1eSDan Willemsen
243*1c12ee1eSDan Willemsenfunc isKnownValue(fd protoreflect.FieldDescriptor) bool {
244*1c12ee1eSDan Willemsen	md := fd.Message()
245*1c12ee1eSDan Willemsen	return md != nil && md.FullName() == genid.Value_message_fullname
246*1c12ee1eSDan Willemsen}
247*1c12ee1eSDan Willemsen
248*1c12ee1eSDan Willemsenfunc isNullValue(fd protoreflect.FieldDescriptor) bool {
249*1c12ee1eSDan Willemsen	ed := fd.Enum()
250*1c12ee1eSDan Willemsen	return ed != nil && ed.FullName() == genid.NullValue_enum_fullname
251*1c12ee1eSDan Willemsen}
252*1c12ee1eSDan Willemsen
253*1c12ee1eSDan Willemsen// unmarshalSingular unmarshals to the non-repeated field specified
254*1c12ee1eSDan Willemsen// by the given FieldDescriptor.
255*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalSingular(m protoreflect.Message, fd protoreflect.FieldDescriptor) error {
256*1c12ee1eSDan Willemsen	var val protoreflect.Value
257*1c12ee1eSDan Willemsen	var err error
258*1c12ee1eSDan Willemsen	switch fd.Kind() {
259*1c12ee1eSDan Willemsen	case protoreflect.MessageKind, protoreflect.GroupKind:
260*1c12ee1eSDan Willemsen		val = m.NewField(fd)
261*1c12ee1eSDan Willemsen		err = d.unmarshalMessage(val.Message(), false)
262*1c12ee1eSDan Willemsen	default:
263*1c12ee1eSDan Willemsen		val, err = d.unmarshalScalar(fd)
264*1c12ee1eSDan Willemsen	}
265*1c12ee1eSDan Willemsen
266*1c12ee1eSDan Willemsen	if err != nil {
267*1c12ee1eSDan Willemsen		return err
268*1c12ee1eSDan Willemsen	}
269*1c12ee1eSDan Willemsen	m.Set(fd, val)
270*1c12ee1eSDan Willemsen	return nil
271*1c12ee1eSDan Willemsen}
272*1c12ee1eSDan Willemsen
273*1c12ee1eSDan Willemsen// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
274*1c12ee1eSDan Willemsen// the given FieldDescriptor.
275*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
276*1c12ee1eSDan Willemsen	const b32 int = 32
277*1c12ee1eSDan Willemsen	const b64 int = 64
278*1c12ee1eSDan Willemsen
279*1c12ee1eSDan Willemsen	tok, err := d.Read()
280*1c12ee1eSDan Willemsen	if err != nil {
281*1c12ee1eSDan Willemsen		return protoreflect.Value{}, err
282*1c12ee1eSDan Willemsen	}
283*1c12ee1eSDan Willemsen
284*1c12ee1eSDan Willemsen	kind := fd.Kind()
285*1c12ee1eSDan Willemsen	switch kind {
286*1c12ee1eSDan Willemsen	case protoreflect.BoolKind:
287*1c12ee1eSDan Willemsen		if tok.Kind() == json.Bool {
288*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBool(tok.Bool()), nil
289*1c12ee1eSDan Willemsen		}
290*1c12ee1eSDan Willemsen
291*1c12ee1eSDan Willemsen	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
292*1c12ee1eSDan Willemsen		if v, ok := unmarshalInt(tok, b32); ok {
293*1c12ee1eSDan Willemsen			return v, nil
294*1c12ee1eSDan Willemsen		}
295*1c12ee1eSDan Willemsen
296*1c12ee1eSDan Willemsen	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
297*1c12ee1eSDan Willemsen		if v, ok := unmarshalInt(tok, b64); ok {
298*1c12ee1eSDan Willemsen			return v, nil
299*1c12ee1eSDan Willemsen		}
300*1c12ee1eSDan Willemsen
301*1c12ee1eSDan Willemsen	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
302*1c12ee1eSDan Willemsen		if v, ok := unmarshalUint(tok, b32); ok {
303*1c12ee1eSDan Willemsen			return v, nil
304*1c12ee1eSDan Willemsen		}
305*1c12ee1eSDan Willemsen
306*1c12ee1eSDan Willemsen	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
307*1c12ee1eSDan Willemsen		if v, ok := unmarshalUint(tok, b64); ok {
308*1c12ee1eSDan Willemsen			return v, nil
309*1c12ee1eSDan Willemsen		}
310*1c12ee1eSDan Willemsen
311*1c12ee1eSDan Willemsen	case protoreflect.FloatKind:
312*1c12ee1eSDan Willemsen		if v, ok := unmarshalFloat(tok, b32); ok {
313*1c12ee1eSDan Willemsen			return v, nil
314*1c12ee1eSDan Willemsen		}
315*1c12ee1eSDan Willemsen
316*1c12ee1eSDan Willemsen	case protoreflect.DoubleKind:
317*1c12ee1eSDan Willemsen		if v, ok := unmarshalFloat(tok, b64); ok {
318*1c12ee1eSDan Willemsen			return v, nil
319*1c12ee1eSDan Willemsen		}
320*1c12ee1eSDan Willemsen
321*1c12ee1eSDan Willemsen	case protoreflect.StringKind:
322*1c12ee1eSDan Willemsen		if tok.Kind() == json.String {
323*1c12ee1eSDan Willemsen			return protoreflect.ValueOfString(tok.ParsedString()), nil
324*1c12ee1eSDan Willemsen		}
325*1c12ee1eSDan Willemsen
326*1c12ee1eSDan Willemsen	case protoreflect.BytesKind:
327*1c12ee1eSDan Willemsen		if v, ok := unmarshalBytes(tok); ok {
328*1c12ee1eSDan Willemsen			return v, nil
329*1c12ee1eSDan Willemsen		}
330*1c12ee1eSDan Willemsen
331*1c12ee1eSDan Willemsen	case protoreflect.EnumKind:
332*1c12ee1eSDan Willemsen		if v, ok := unmarshalEnum(tok, fd); ok {
333*1c12ee1eSDan Willemsen			return v, nil
334*1c12ee1eSDan Willemsen		}
335*1c12ee1eSDan Willemsen
336*1c12ee1eSDan Willemsen	default:
337*1c12ee1eSDan Willemsen		panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind))
338*1c12ee1eSDan Willemsen	}
339*1c12ee1eSDan Willemsen
340*1c12ee1eSDan Willemsen	return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString())
341*1c12ee1eSDan Willemsen}
342*1c12ee1eSDan Willemsen
343*1c12ee1eSDan Willemsenfunc unmarshalInt(tok json.Token, bitSize int) (protoreflect.Value, bool) {
344*1c12ee1eSDan Willemsen	switch tok.Kind() {
345*1c12ee1eSDan Willemsen	case json.Number:
346*1c12ee1eSDan Willemsen		return getInt(tok, bitSize)
347*1c12ee1eSDan Willemsen
348*1c12ee1eSDan Willemsen	case json.String:
349*1c12ee1eSDan Willemsen		// Decode number from string.
350*1c12ee1eSDan Willemsen		s := strings.TrimSpace(tok.ParsedString())
351*1c12ee1eSDan Willemsen		if len(s) != len(tok.ParsedString()) {
352*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
353*1c12ee1eSDan Willemsen		}
354*1c12ee1eSDan Willemsen		dec := json.NewDecoder([]byte(s))
355*1c12ee1eSDan Willemsen		tok, err := dec.Read()
356*1c12ee1eSDan Willemsen		if err != nil {
357*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
358*1c12ee1eSDan Willemsen		}
359*1c12ee1eSDan Willemsen		return getInt(tok, bitSize)
360*1c12ee1eSDan Willemsen	}
361*1c12ee1eSDan Willemsen	return protoreflect.Value{}, false
362*1c12ee1eSDan Willemsen}
363*1c12ee1eSDan Willemsen
364*1c12ee1eSDan Willemsenfunc getInt(tok json.Token, bitSize int) (protoreflect.Value, bool) {
365*1c12ee1eSDan Willemsen	n, ok := tok.Int(bitSize)
366*1c12ee1eSDan Willemsen	if !ok {
367*1c12ee1eSDan Willemsen		return protoreflect.Value{}, false
368*1c12ee1eSDan Willemsen	}
369*1c12ee1eSDan Willemsen	if bitSize == 32 {
370*1c12ee1eSDan Willemsen		return protoreflect.ValueOfInt32(int32(n)), true
371*1c12ee1eSDan Willemsen	}
372*1c12ee1eSDan Willemsen	return protoreflect.ValueOfInt64(n), true
373*1c12ee1eSDan Willemsen}
374*1c12ee1eSDan Willemsen
375*1c12ee1eSDan Willemsenfunc unmarshalUint(tok json.Token, bitSize int) (protoreflect.Value, bool) {
376*1c12ee1eSDan Willemsen	switch tok.Kind() {
377*1c12ee1eSDan Willemsen	case json.Number:
378*1c12ee1eSDan Willemsen		return getUint(tok, bitSize)
379*1c12ee1eSDan Willemsen
380*1c12ee1eSDan Willemsen	case json.String:
381*1c12ee1eSDan Willemsen		// Decode number from string.
382*1c12ee1eSDan Willemsen		s := strings.TrimSpace(tok.ParsedString())
383*1c12ee1eSDan Willemsen		if len(s) != len(tok.ParsedString()) {
384*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
385*1c12ee1eSDan Willemsen		}
386*1c12ee1eSDan Willemsen		dec := json.NewDecoder([]byte(s))
387*1c12ee1eSDan Willemsen		tok, err := dec.Read()
388*1c12ee1eSDan Willemsen		if err != nil {
389*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
390*1c12ee1eSDan Willemsen		}
391*1c12ee1eSDan Willemsen		return getUint(tok, bitSize)
392*1c12ee1eSDan Willemsen	}
393*1c12ee1eSDan Willemsen	return protoreflect.Value{}, false
394*1c12ee1eSDan Willemsen}
395*1c12ee1eSDan Willemsen
396*1c12ee1eSDan Willemsenfunc getUint(tok json.Token, bitSize int) (protoreflect.Value, bool) {
397*1c12ee1eSDan Willemsen	n, ok := tok.Uint(bitSize)
398*1c12ee1eSDan Willemsen	if !ok {
399*1c12ee1eSDan Willemsen		return protoreflect.Value{}, false
400*1c12ee1eSDan Willemsen	}
401*1c12ee1eSDan Willemsen	if bitSize == 32 {
402*1c12ee1eSDan Willemsen		return protoreflect.ValueOfUint32(uint32(n)), true
403*1c12ee1eSDan Willemsen	}
404*1c12ee1eSDan Willemsen	return protoreflect.ValueOfUint64(n), true
405*1c12ee1eSDan Willemsen}
406*1c12ee1eSDan Willemsen
407*1c12ee1eSDan Willemsenfunc unmarshalFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) {
408*1c12ee1eSDan Willemsen	switch tok.Kind() {
409*1c12ee1eSDan Willemsen	case json.Number:
410*1c12ee1eSDan Willemsen		return getFloat(tok, bitSize)
411*1c12ee1eSDan Willemsen
412*1c12ee1eSDan Willemsen	case json.String:
413*1c12ee1eSDan Willemsen		s := tok.ParsedString()
414*1c12ee1eSDan Willemsen		switch s {
415*1c12ee1eSDan Willemsen		case "NaN":
416*1c12ee1eSDan Willemsen			if bitSize == 32 {
417*1c12ee1eSDan Willemsen				return protoreflect.ValueOfFloat32(float32(math.NaN())), true
418*1c12ee1eSDan Willemsen			}
419*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(math.NaN()), true
420*1c12ee1eSDan Willemsen		case "Infinity":
421*1c12ee1eSDan Willemsen			if bitSize == 32 {
422*1c12ee1eSDan Willemsen				return protoreflect.ValueOfFloat32(float32(math.Inf(+1))), true
423*1c12ee1eSDan Willemsen			}
424*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(math.Inf(+1)), true
425*1c12ee1eSDan Willemsen		case "-Infinity":
426*1c12ee1eSDan Willemsen			if bitSize == 32 {
427*1c12ee1eSDan Willemsen				return protoreflect.ValueOfFloat32(float32(math.Inf(-1))), true
428*1c12ee1eSDan Willemsen			}
429*1c12ee1eSDan Willemsen			return protoreflect.ValueOfFloat64(math.Inf(-1)), true
430*1c12ee1eSDan Willemsen		}
431*1c12ee1eSDan Willemsen
432*1c12ee1eSDan Willemsen		// Decode number from string.
433*1c12ee1eSDan Willemsen		if len(s) != len(strings.TrimSpace(s)) {
434*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
435*1c12ee1eSDan Willemsen		}
436*1c12ee1eSDan Willemsen		dec := json.NewDecoder([]byte(s))
437*1c12ee1eSDan Willemsen		tok, err := dec.Read()
438*1c12ee1eSDan Willemsen		if err != nil {
439*1c12ee1eSDan Willemsen			return protoreflect.Value{}, false
440*1c12ee1eSDan Willemsen		}
441*1c12ee1eSDan Willemsen		return getFloat(tok, bitSize)
442*1c12ee1eSDan Willemsen	}
443*1c12ee1eSDan Willemsen	return protoreflect.Value{}, false
444*1c12ee1eSDan Willemsen}
445*1c12ee1eSDan Willemsen
446*1c12ee1eSDan Willemsenfunc getFloat(tok json.Token, bitSize int) (protoreflect.Value, bool) {
447*1c12ee1eSDan Willemsen	n, ok := tok.Float(bitSize)
448*1c12ee1eSDan Willemsen	if !ok {
449*1c12ee1eSDan Willemsen		return protoreflect.Value{}, false
450*1c12ee1eSDan Willemsen	}
451*1c12ee1eSDan Willemsen	if bitSize == 32 {
452*1c12ee1eSDan Willemsen		return protoreflect.ValueOfFloat32(float32(n)), true
453*1c12ee1eSDan Willemsen	}
454*1c12ee1eSDan Willemsen	return protoreflect.ValueOfFloat64(n), true
455*1c12ee1eSDan Willemsen}
456*1c12ee1eSDan Willemsen
457*1c12ee1eSDan Willemsenfunc unmarshalBytes(tok json.Token) (protoreflect.Value, bool) {
458*1c12ee1eSDan Willemsen	if tok.Kind() != json.String {
459*1c12ee1eSDan Willemsen		return protoreflect.Value{}, false
460*1c12ee1eSDan Willemsen	}
461*1c12ee1eSDan Willemsen
462*1c12ee1eSDan Willemsen	s := tok.ParsedString()
463*1c12ee1eSDan Willemsen	enc := base64.StdEncoding
464*1c12ee1eSDan Willemsen	if strings.ContainsAny(s, "-_") {
465*1c12ee1eSDan Willemsen		enc = base64.URLEncoding
466*1c12ee1eSDan Willemsen	}
467*1c12ee1eSDan Willemsen	if len(s)%4 != 0 {
468*1c12ee1eSDan Willemsen		enc = enc.WithPadding(base64.NoPadding)
469*1c12ee1eSDan Willemsen	}
470*1c12ee1eSDan Willemsen	b, err := enc.DecodeString(s)
471*1c12ee1eSDan Willemsen	if err != nil {
472*1c12ee1eSDan Willemsen		return protoreflect.Value{}, false
473*1c12ee1eSDan Willemsen	}
474*1c12ee1eSDan Willemsen	return protoreflect.ValueOfBytes(b), true
475*1c12ee1eSDan Willemsen}
476*1c12ee1eSDan Willemsen
477*1c12ee1eSDan Willemsenfunc unmarshalEnum(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.Value, bool) {
478*1c12ee1eSDan Willemsen	switch tok.Kind() {
479*1c12ee1eSDan Willemsen	case json.String:
480*1c12ee1eSDan Willemsen		// Lookup EnumNumber based on name.
481*1c12ee1eSDan Willemsen		s := tok.ParsedString()
482*1c12ee1eSDan Willemsen		if enumVal := fd.Enum().Values().ByName(protoreflect.Name(s)); enumVal != nil {
483*1c12ee1eSDan Willemsen			return protoreflect.ValueOfEnum(enumVal.Number()), true
484*1c12ee1eSDan Willemsen		}
485*1c12ee1eSDan Willemsen
486*1c12ee1eSDan Willemsen	case json.Number:
487*1c12ee1eSDan Willemsen		if n, ok := tok.Int(32); ok {
488*1c12ee1eSDan Willemsen			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(n)), true
489*1c12ee1eSDan Willemsen		}
490*1c12ee1eSDan Willemsen
491*1c12ee1eSDan Willemsen	case json.Null:
492*1c12ee1eSDan Willemsen		// This is only valid for google.protobuf.NullValue.
493*1c12ee1eSDan Willemsen		if isNullValue(fd) {
494*1c12ee1eSDan Willemsen			return protoreflect.ValueOfEnum(0), true
495*1c12ee1eSDan Willemsen		}
496*1c12ee1eSDan Willemsen	}
497*1c12ee1eSDan Willemsen
498*1c12ee1eSDan Willemsen	return protoreflect.Value{}, false
499*1c12ee1eSDan Willemsen}
500*1c12ee1eSDan Willemsen
501*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error {
502*1c12ee1eSDan Willemsen	tok, err := d.Read()
503*1c12ee1eSDan Willemsen	if err != nil {
504*1c12ee1eSDan Willemsen		return err
505*1c12ee1eSDan Willemsen	}
506*1c12ee1eSDan Willemsen	if tok.Kind() != json.ArrayOpen {
507*1c12ee1eSDan Willemsen		return d.unexpectedTokenError(tok)
508*1c12ee1eSDan Willemsen	}
509*1c12ee1eSDan Willemsen
510*1c12ee1eSDan Willemsen	switch fd.Kind() {
511*1c12ee1eSDan Willemsen	case protoreflect.MessageKind, protoreflect.GroupKind:
512*1c12ee1eSDan Willemsen		for {
513*1c12ee1eSDan Willemsen			tok, err := d.Peek()
514*1c12ee1eSDan Willemsen			if err != nil {
515*1c12ee1eSDan Willemsen				return err
516*1c12ee1eSDan Willemsen			}
517*1c12ee1eSDan Willemsen
518*1c12ee1eSDan Willemsen			if tok.Kind() == json.ArrayClose {
519*1c12ee1eSDan Willemsen				d.Read()
520*1c12ee1eSDan Willemsen				return nil
521*1c12ee1eSDan Willemsen			}
522*1c12ee1eSDan Willemsen
523*1c12ee1eSDan Willemsen			val := list.NewElement()
524*1c12ee1eSDan Willemsen			if err := d.unmarshalMessage(val.Message(), false); err != nil {
525*1c12ee1eSDan Willemsen				return err
526*1c12ee1eSDan Willemsen			}
527*1c12ee1eSDan Willemsen			list.Append(val)
528*1c12ee1eSDan Willemsen		}
529*1c12ee1eSDan Willemsen	default:
530*1c12ee1eSDan Willemsen		for {
531*1c12ee1eSDan Willemsen			tok, err := d.Peek()
532*1c12ee1eSDan Willemsen			if err != nil {
533*1c12ee1eSDan Willemsen				return err
534*1c12ee1eSDan Willemsen			}
535*1c12ee1eSDan Willemsen
536*1c12ee1eSDan Willemsen			if tok.Kind() == json.ArrayClose {
537*1c12ee1eSDan Willemsen				d.Read()
538*1c12ee1eSDan Willemsen				return nil
539*1c12ee1eSDan Willemsen			}
540*1c12ee1eSDan Willemsen
541*1c12ee1eSDan Willemsen			val, err := d.unmarshalScalar(fd)
542*1c12ee1eSDan Willemsen			if err != nil {
543*1c12ee1eSDan Willemsen				return err
544*1c12ee1eSDan Willemsen			}
545*1c12ee1eSDan Willemsen			list.Append(val)
546*1c12ee1eSDan Willemsen		}
547*1c12ee1eSDan Willemsen	}
548*1c12ee1eSDan Willemsen
549*1c12ee1eSDan Willemsen	return nil
550*1c12ee1eSDan Willemsen}
551*1c12ee1eSDan Willemsen
552*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error {
553*1c12ee1eSDan Willemsen	tok, err := d.Read()
554*1c12ee1eSDan Willemsen	if err != nil {
555*1c12ee1eSDan Willemsen		return err
556*1c12ee1eSDan Willemsen	}
557*1c12ee1eSDan Willemsen	if tok.Kind() != json.ObjectOpen {
558*1c12ee1eSDan Willemsen		return d.unexpectedTokenError(tok)
559*1c12ee1eSDan Willemsen	}
560*1c12ee1eSDan Willemsen
561*1c12ee1eSDan Willemsen	// Determine ahead whether map entry is a scalar type or a message type in
562*1c12ee1eSDan Willemsen	// order to call the appropriate unmarshalMapValue func inside the for loop
563*1c12ee1eSDan Willemsen	// below.
564*1c12ee1eSDan Willemsen	var unmarshalMapValue func() (protoreflect.Value, error)
565*1c12ee1eSDan Willemsen	switch fd.MapValue().Kind() {
566*1c12ee1eSDan Willemsen	case protoreflect.MessageKind, protoreflect.GroupKind:
567*1c12ee1eSDan Willemsen		unmarshalMapValue = func() (protoreflect.Value, error) {
568*1c12ee1eSDan Willemsen			val := mmap.NewValue()
569*1c12ee1eSDan Willemsen			if err := d.unmarshalMessage(val.Message(), false); err != nil {
570*1c12ee1eSDan Willemsen				return protoreflect.Value{}, err
571*1c12ee1eSDan Willemsen			}
572*1c12ee1eSDan Willemsen			return val, nil
573*1c12ee1eSDan Willemsen		}
574*1c12ee1eSDan Willemsen	default:
575*1c12ee1eSDan Willemsen		unmarshalMapValue = func() (protoreflect.Value, error) {
576*1c12ee1eSDan Willemsen			return d.unmarshalScalar(fd.MapValue())
577*1c12ee1eSDan Willemsen		}
578*1c12ee1eSDan Willemsen	}
579*1c12ee1eSDan Willemsen
580*1c12ee1eSDan WillemsenLoop:
581*1c12ee1eSDan Willemsen	for {
582*1c12ee1eSDan Willemsen		// Read field name.
583*1c12ee1eSDan Willemsen		tok, err := d.Read()
584*1c12ee1eSDan Willemsen		if err != nil {
585*1c12ee1eSDan Willemsen			return err
586*1c12ee1eSDan Willemsen		}
587*1c12ee1eSDan Willemsen		switch tok.Kind() {
588*1c12ee1eSDan Willemsen		default:
589*1c12ee1eSDan Willemsen			return d.unexpectedTokenError(tok)
590*1c12ee1eSDan Willemsen		case json.ObjectClose:
591*1c12ee1eSDan Willemsen			break Loop
592*1c12ee1eSDan Willemsen		case json.Name:
593*1c12ee1eSDan Willemsen			// Continue.
594*1c12ee1eSDan Willemsen		}
595*1c12ee1eSDan Willemsen
596*1c12ee1eSDan Willemsen		// Unmarshal field name.
597*1c12ee1eSDan Willemsen		pkey, err := d.unmarshalMapKey(tok, fd.MapKey())
598*1c12ee1eSDan Willemsen		if err != nil {
599*1c12ee1eSDan Willemsen			return err
600*1c12ee1eSDan Willemsen		}
601*1c12ee1eSDan Willemsen
602*1c12ee1eSDan Willemsen		// Check for duplicate field name.
603*1c12ee1eSDan Willemsen		if mmap.Has(pkey) {
604*1c12ee1eSDan Willemsen			return d.newError(tok.Pos(), "duplicate map key %v", tok.RawString())
605*1c12ee1eSDan Willemsen		}
606*1c12ee1eSDan Willemsen
607*1c12ee1eSDan Willemsen		// Read and unmarshal field value.
608*1c12ee1eSDan Willemsen		pval, err := unmarshalMapValue()
609*1c12ee1eSDan Willemsen		if err != nil {
610*1c12ee1eSDan Willemsen			return err
611*1c12ee1eSDan Willemsen		}
612*1c12ee1eSDan Willemsen
613*1c12ee1eSDan Willemsen		mmap.Set(pkey, pval)
614*1c12ee1eSDan Willemsen	}
615*1c12ee1eSDan Willemsen
616*1c12ee1eSDan Willemsen	return nil
617*1c12ee1eSDan Willemsen}
618*1c12ee1eSDan Willemsen
619*1c12ee1eSDan Willemsen// unmarshalMapKey converts given token of Name kind into a protoreflect.MapKey.
620*1c12ee1eSDan Willemsen// A map key type is any integral or string type.
621*1c12ee1eSDan Willemsenfunc (d decoder) unmarshalMapKey(tok json.Token, fd protoreflect.FieldDescriptor) (protoreflect.MapKey, error) {
622*1c12ee1eSDan Willemsen	const b32 = 32
623*1c12ee1eSDan Willemsen	const b64 = 64
624*1c12ee1eSDan Willemsen	const base10 = 10
625*1c12ee1eSDan Willemsen
626*1c12ee1eSDan Willemsen	name := tok.Name()
627*1c12ee1eSDan Willemsen	kind := fd.Kind()
628*1c12ee1eSDan Willemsen	switch kind {
629*1c12ee1eSDan Willemsen	case protoreflect.StringKind:
630*1c12ee1eSDan Willemsen		return protoreflect.ValueOfString(name).MapKey(), nil
631*1c12ee1eSDan Willemsen
632*1c12ee1eSDan Willemsen	case protoreflect.BoolKind:
633*1c12ee1eSDan Willemsen		switch name {
634*1c12ee1eSDan Willemsen		case "true":
635*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBool(true).MapKey(), nil
636*1c12ee1eSDan Willemsen		case "false":
637*1c12ee1eSDan Willemsen			return protoreflect.ValueOfBool(false).MapKey(), nil
638*1c12ee1eSDan Willemsen		}
639*1c12ee1eSDan Willemsen
640*1c12ee1eSDan Willemsen	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
641*1c12ee1eSDan Willemsen		if n, err := strconv.ParseInt(name, base10, b32); err == nil {
642*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt32(int32(n)).MapKey(), nil
643*1c12ee1eSDan Willemsen		}
644*1c12ee1eSDan Willemsen
645*1c12ee1eSDan Willemsen	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
646*1c12ee1eSDan Willemsen		if n, err := strconv.ParseInt(name, base10, b64); err == nil {
647*1c12ee1eSDan Willemsen			return protoreflect.ValueOfInt64(int64(n)).MapKey(), nil
648*1c12ee1eSDan Willemsen		}
649*1c12ee1eSDan Willemsen
650*1c12ee1eSDan Willemsen	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
651*1c12ee1eSDan Willemsen		if n, err := strconv.ParseUint(name, base10, b32); err == nil {
652*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint32(uint32(n)).MapKey(), nil
653*1c12ee1eSDan Willemsen		}
654*1c12ee1eSDan Willemsen
655*1c12ee1eSDan Willemsen	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
656*1c12ee1eSDan Willemsen		if n, err := strconv.ParseUint(name, base10, b64); err == nil {
657*1c12ee1eSDan Willemsen			return protoreflect.ValueOfUint64(uint64(n)).MapKey(), nil
658*1c12ee1eSDan Willemsen		}
659*1c12ee1eSDan Willemsen
660*1c12ee1eSDan Willemsen	default:
661*1c12ee1eSDan Willemsen		panic(fmt.Sprintf("invalid kind for map key: %v", kind))
662*1c12ee1eSDan Willemsen	}
663*1c12ee1eSDan Willemsen
664*1c12ee1eSDan Willemsen	return protoreflect.MapKey{}, d.newError(tok.Pos(), "invalid value for %v key: %s", kind, tok.RawString())
665*1c12ee1eSDan Willemsen}
666