blob: 221adc79044a28043ea399fb3e9abcdf0d6fbde4 [file] [log] [blame]
Herbie Ongc96a79d2019-03-08 10:49:17 -08001// 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.
4
5package jsonpb
6
7import (
8 "encoding/base64"
9 "fmt"
10 "math"
11 "strconv"
12 "strings"
13
14 "github.com/golang/protobuf/v2/internal/encoding/json"
15 "github.com/golang/protobuf/v2/internal/errors"
Herbie Onge52379a2019-03-15 18:00:19 -070016 "github.com/golang/protobuf/v2/internal/pragma"
Herbie Ongc96a79d2019-03-08 10:49:17 -080017 "github.com/golang/protobuf/v2/internal/set"
18 "github.com/golang/protobuf/v2/proto"
19 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
Herbie Onge52379a2019-03-15 18:00:19 -070020 "github.com/golang/protobuf/v2/reflect/protoregistry"
Herbie Ongc96a79d2019-03-08 10:49:17 -080021)
22
23// Unmarshal reads the given []byte into the given proto.Message.
24func Unmarshal(m proto.Message, b []byte) error {
25 return UnmarshalOptions{}.Unmarshal(m, b)
26}
27
28// UnmarshalOptions is a configurable JSON format parser.
Herbie Onge52379a2019-03-15 18:00:19 -070029type UnmarshalOptions struct {
30 pragma.NoUnkeyedLiterals
31
32 // Resolver is the registry used for type lookups when unmarshaling extensions
33 // and processing Any. If Resolver is not set, unmarshaling will default to
34 // using protoregistry.GlobalTypes.
35 Resolver *protoregistry.Types
Herbie Ong822de2d2019-03-27 13:16:23 -070036
37 decoder *json.Decoder
Herbie Onge52379a2019-03-15 18:00:19 -070038}
Herbie Ongc96a79d2019-03-08 10:49:17 -080039
40// Unmarshal reads the given []byte and populates the given proto.Message using
41// options in UnmarshalOptions object. It will clear the message first before
42// setting the fields. If it returns an error, the given message may be
43// partially set.
44func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
45 mr := m.ProtoReflect()
46 // TODO: Determine if we would like to have an option for merging or only
47 // have merging behavior. We should at least be consistent with textproto
48 // marshaling.
49 resetMessage(mr)
50
Herbie Ong822de2d2019-03-27 13:16:23 -070051 if o.Resolver == nil {
52 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070053 }
Herbie Ong822de2d2019-03-27 13:16:23 -070054 o.decoder = json.NewDecoder(b)
Herbie Onge52379a2019-03-15 18:00:19 -070055
Herbie Ongc96a79d2019-03-08 10:49:17 -080056 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -070057 if err := o.unmarshalMessage(mr); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -080058 return err
59 }
60
61 // Check for EOF.
Herbie Ong822de2d2019-03-27 13:16:23 -070062 val, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080063 if err != nil {
64 return err
65 }
66 if val.Type() != json.EOF {
67 return unexpectedJSONError{val}
68 }
69 return nerr.E
70}
71
72// resetMessage clears all fields of given protoreflect.Message.
73func resetMessage(m pref.Message) {
74 knownFields := m.KnownFields()
75 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
76 knownFields.Clear(num)
77 return true
78 })
79 unknownFields := m.UnknownFields()
80 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
81 unknownFields.Set(num, nil)
82 return true
83 })
84 extTypes := knownFields.ExtensionTypes()
85 extTypes.Range(func(xt pref.ExtensionType) bool {
86 extTypes.Remove(xt)
87 return true
88 })
89}
90
91// unexpectedJSONError is an error that contains the unexpected json.Value. This
Herbie Ong822de2d2019-03-27 13:16:23 -070092// is returned by methods to provide callers the read json.Value that it did not
93// expect.
Herbie Ongc96a79d2019-03-08 10:49:17 -080094// TODO: Consider moving this to internal/encoding/json for consistency with
95// errors that package returns.
96type unexpectedJSONError struct {
97 value json.Value
98}
99
100func (e unexpectedJSONError) Error() string {
101 return newError("unexpected value %s", e.value).Error()
102}
103
104// newError returns an error object. If one of the values passed in is of
105// json.Value type, it produces an error with position info.
106func newError(f string, x ...interface{}) error {
107 var hasValue bool
108 var line, column int
109 for i := 0; i < len(x); i++ {
110 if val, ok := x[i].(json.Value); ok {
111 line, column = val.Position()
112 hasValue = true
113 break
114 }
115 }
116 e := errors.New(f, x...)
117 if hasValue {
118 return errors.New("(line %d:%d): %v", line, column, e)
119 }
120 return e
121}
122
Herbie Ongc96a79d2019-03-08 10:49:17 -0800123// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -0700124func (o UnmarshalOptions) unmarshalMessage(m pref.Message) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800125 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800126
Herbie Onge63c4c42019-03-22 22:20:22 -0700127 if isCustomType(m.Type().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700128 return o.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700129 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800130
Herbie Ong822de2d2019-03-27 13:16:23 -0700131 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800132 if !nerr.Merge(err) {
133 return err
134 }
135 if jval.Type() != json.StartObject {
136 return unexpectedJSONError{jval}
137 }
138
Herbie Ong822de2d2019-03-27 13:16:23 -0700139 if err := o.unmarshalFields(m); !nerr.Merge(err) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700140 return err
141 }
142
143 return nerr.E
144}
145
146// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -0700147func (o UnmarshalOptions) unmarshalFields(m pref.Message) error {
Herbie Onge63c4c42019-03-22 22:20:22 -0700148 var nerr errors.NonFatal
149 var reqNums set.Ints
150 var seenNums set.Ints
151
152 msgType := m.Type()
153 knownFields := m.KnownFields()
154 fieldDescs := msgType.Fields()
155 xtTypes := knownFields.ExtensionTypes()
156
Herbie Ongc96a79d2019-03-08 10:49:17 -0800157Loop:
158 for {
159 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700160 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800161 if !nerr.Merge(err) {
162 return err
163 }
164 switch jval.Type() {
165 default:
166 return unexpectedJSONError{jval}
167 case json.EndObject:
168 break Loop
169 case json.Name:
170 // Continue below.
171 }
172
173 name, err := jval.Name()
174 if !nerr.Merge(err) {
175 return err
176 }
177
Herbie Onge52379a2019-03-15 18:00:19 -0700178 // Get the FieldDescriptor.
179 var fd pref.FieldDescriptor
180 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
181 // Only extension names are in [name] format.
182 xtName := pref.FullName(name[1 : len(name)-1])
183 xt := xtTypes.ByName(xtName)
184 if xt == nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700185 xt, err = o.findExtension(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700186 if err != nil && err != protoregistry.NotFound {
187 return errors.New("unable to resolve [%v]: %v", xtName, err)
188 }
189 if xt != nil {
190 xtTypes.Register(xt)
191 }
192 }
193 fd = xt
194 } else {
195 // The name can either be the JSON name or the proto field name.
196 fd = fieldDescs.ByJSONName(name)
197 if fd == nil {
198 fd = fieldDescs.ByName(pref.Name(name))
199 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800200 }
201
202 if fd == nil {
203 // Field is unknown.
204 // TODO: Provide option to ignore unknown message fields.
205 return newError("%v contains unknown field %s", msgType.FullName(), jval)
206 }
207
208 // Do not allow duplicate fields.
209 num := uint64(fd.Number())
210 if seenNums.Has(num) {
211 return newError("%v contains repeated field %s", msgType.FullName(), jval)
212 }
213 seenNums.Set(num)
214
Herbie Onge63c4c42019-03-22 22:20:22 -0700215 // No need to set values for JSON null unless the field type is
216 // google.protobuf.Value.
Herbie Ong822de2d2019-03-27 13:16:23 -0700217 if o.decoder.Peek() == json.Null && !isKnownValue(fd) {
218 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800219 continue
220 }
221
222 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
223 // Map or list fields have cardinality of repeated.
Herbie Ong822de2d2019-03-27 13:16:23 -0700224 if err := o.unmarshalRepeated(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800225 return errors.New("%v|%q: %v", fd.FullName(), name, err)
226 }
227 } else {
228 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700229 if err := o.unmarshalSingular(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800230 return errors.New("%v|%q: %v", fd.FullName(), name, err)
231 }
232 if cardinality == pref.Required {
233 reqNums.Set(num)
234 }
235 }
236 }
237
238 // Check for any missing required fields.
239 allReqNums := msgType.RequiredNumbers()
240 if reqNums.Len() != allReqNums.Len() {
241 for i := 0; i < allReqNums.Len(); i++ {
242 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
243 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
244 }
245 }
246 }
247
248 return nerr.E
249}
250
Herbie Onge52379a2019-03-15 18:00:19 -0700251// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700252func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
253 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700254 if err == nil {
255 return xt, nil
256 }
257
258 // Check if this is a MessageSet extension field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700259 xt, err = o.Resolver.FindExtensionByName(xtName + ".message_set_extension")
Herbie Onge52379a2019-03-15 18:00:19 -0700260 if err == nil && isMessageSetExtension(xt) {
261 return xt, nil
262 }
263 return nil, protoregistry.NotFound
264}
265
Herbie Ongc96a79d2019-03-08 10:49:17 -0800266// unmarshalSingular unmarshals to the non-repeated field specified by the given
267// FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700268func (o UnmarshalOptions) unmarshalSingular(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800269 var val pref.Value
270 var err error
271 num := fd.Number()
272
273 switch fd.Kind() {
274 case pref.MessageKind, pref.GroupKind:
275 m := knownFields.NewMessage(num)
Herbie Ong822de2d2019-03-27 13:16:23 -0700276 err = o.unmarshalMessage(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800277 val = pref.ValueOf(m)
278 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700279 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800280 }
281
282 var nerr errors.NonFatal
283 if !nerr.Merge(err) {
284 return err
285 }
286 knownFields.Set(num, val)
287 return nerr.E
288}
289
290// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
291// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700292func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800293 const b32 int = 32
294 const b64 int = 64
295
296 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700297 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800298 if !nerr.Merge(err) {
299 return pref.Value{}, err
300 }
301
302 kind := fd.Kind()
303 switch kind {
304 case pref.BoolKind:
305 return unmarshalBool(jval)
306
307 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
308 return unmarshalInt(jval, b32)
309
310 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
311 return unmarshalInt(jval, b64)
312
313 case pref.Uint32Kind, pref.Fixed32Kind:
314 return unmarshalUint(jval, b32)
315
316 case pref.Uint64Kind, pref.Fixed64Kind:
317 return unmarshalUint(jval, b64)
318
319 case pref.FloatKind:
320 return unmarshalFloat(jval, b32)
321
322 case pref.DoubleKind:
323 return unmarshalFloat(jval, b64)
324
325 case pref.StringKind:
326 pval, err := unmarshalString(jval)
327 if !nerr.Merge(err) {
328 return pval, err
329 }
330 return pval, nerr.E
331
332 case pref.BytesKind:
333 return unmarshalBytes(jval)
334
335 case pref.EnumKind:
336 return unmarshalEnum(jval, fd)
337 }
338
339 panic(fmt.Sprintf("invalid scalar kind %v", kind))
340}
341
342func unmarshalBool(jval json.Value) (pref.Value, error) {
343 if jval.Type() != json.Bool {
344 return pref.Value{}, unexpectedJSONError{jval}
345 }
346 b, err := jval.Bool()
347 return pref.ValueOf(b), err
348}
349
350func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
351 switch jval.Type() {
352 case json.Number:
353 return getInt(jval, bitSize)
354
355 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700356 // Decode number from string.
357 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800358 var nerr errors.NonFatal
359 jval, err := dec.Read()
360 if !nerr.Merge(err) {
361 return pref.Value{}, err
362 }
363 return getInt(jval, bitSize)
364 }
365 return pref.Value{}, unexpectedJSONError{jval}
366}
367
368func getInt(jval json.Value, bitSize int) (pref.Value, error) {
369 n, err := jval.Int(bitSize)
370 if err != nil {
371 return pref.Value{}, err
372 }
373 if bitSize == 32 {
374 return pref.ValueOf(int32(n)), nil
375 }
376 return pref.ValueOf(n), nil
377}
378
379func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
380 switch jval.Type() {
381 case json.Number:
382 return getUint(jval, bitSize)
383
384 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700385 // Decode number from string.
386 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800387 var nerr errors.NonFatal
388 jval, err := dec.Read()
389 if !nerr.Merge(err) {
390 return pref.Value{}, err
391 }
392 return getUint(jval, bitSize)
393 }
394 return pref.Value{}, unexpectedJSONError{jval}
395}
396
397func getUint(jval json.Value, bitSize int) (pref.Value, error) {
398 n, err := jval.Uint(bitSize)
399 if err != nil {
400 return pref.Value{}, err
401 }
402 if bitSize == 32 {
403 return pref.ValueOf(uint32(n)), nil
404 }
405 return pref.ValueOf(n), nil
406}
407
408func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
409 switch jval.Type() {
410 case json.Number:
411 return getFloat(jval, bitSize)
412
413 case json.String:
414 s := jval.String()
415 switch s {
416 case "NaN":
417 if bitSize == 32 {
418 return pref.ValueOf(float32(math.NaN())), nil
419 }
420 return pref.ValueOf(math.NaN()), nil
421 case "Infinity":
422 if bitSize == 32 {
423 return pref.ValueOf(float32(math.Inf(+1))), nil
424 }
425 return pref.ValueOf(math.Inf(+1)), nil
426 case "-Infinity":
427 if bitSize == 32 {
428 return pref.ValueOf(float32(math.Inf(-1))), nil
429 }
430 return pref.ValueOf(math.Inf(-1)), nil
431 }
Herbie Onge52379a2019-03-15 18:00:19 -0700432 // Decode number from string.
433 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800434 var nerr errors.NonFatal
435 jval, err := dec.Read()
436 if !nerr.Merge(err) {
437 return pref.Value{}, err
438 }
439 return getFloat(jval, bitSize)
440 }
441 return pref.Value{}, unexpectedJSONError{jval}
442}
443
444func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
445 n, err := jval.Float(bitSize)
446 if err != nil {
447 return pref.Value{}, err
448 }
449 if bitSize == 32 {
450 return pref.ValueOf(float32(n)), nil
451 }
452 return pref.ValueOf(n), nil
453}
454
455func unmarshalString(jval json.Value) (pref.Value, error) {
456 if jval.Type() != json.String {
457 return pref.Value{}, unexpectedJSONError{jval}
458 }
459 return pref.ValueOf(jval.String()), nil
460}
461
462func unmarshalBytes(jval json.Value) (pref.Value, error) {
463 if jval.Type() != json.String {
464 return pref.Value{}, unexpectedJSONError{jval}
465 }
466
467 s := jval.String()
468 enc := base64.StdEncoding
469 if strings.ContainsAny(s, "-_") {
470 enc = base64.URLEncoding
471 }
472 if len(s)%4 != 0 {
473 enc = enc.WithPadding(base64.NoPadding)
474 }
475 b, err := enc.DecodeString(s)
476 if err != nil {
477 return pref.Value{}, err
478 }
479 return pref.ValueOf(b), nil
480}
481
482func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
483 switch jval.Type() {
484 case json.String:
485 // Lookup EnumNumber based on name.
486 s := jval.String()
487 if enumVal := fd.EnumType().Values().ByName(pref.Name(s)); enumVal != nil {
488 return pref.ValueOf(enumVal.Number()), nil
489 }
490 return pref.Value{}, newError("invalid enum value %q", jval)
491
492 case json.Number:
493 n, err := jval.Int(32)
494 if err != nil {
495 return pref.Value{}, err
496 }
497 return pref.ValueOf(pref.EnumNumber(n)), nil
498 }
499
500 return pref.Value{}, unexpectedJSONError{jval}
501}
502
503// unmarshalRepeated unmarshals into a repeated field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700504func (o UnmarshalOptions) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800505 var nerr errors.NonFatal
506 num := fd.Number()
507 val := knownFields.Get(num)
508 if !fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700509 if err := o.unmarshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800510 return err
511 }
512 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700513 if err := o.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800514 return err
515 }
516 }
517 return nerr.E
518}
519
520// unmarshalList unmarshals into given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700521func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800522 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700523 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800524 if !nerr.Merge(err) {
525 return err
526 }
527 if jval.Type() != json.StartArray {
528 return unexpectedJSONError{jval}
529 }
530
531 switch fd.Kind() {
532 case pref.MessageKind, pref.GroupKind:
533 for {
534 m := list.NewMessage()
Herbie Ong822de2d2019-03-27 13:16:23 -0700535 err := o.unmarshalMessage(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800536 if !nerr.Merge(err) {
537 if e, ok := err.(unexpectedJSONError); ok {
538 if e.value.Type() == json.EndArray {
539 // Done with list.
540 return nerr.E
541 }
542 }
543 return err
544 }
545 list.Append(pref.ValueOf(m))
546 }
547 default:
548 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700549 val, err := o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800550 if !nerr.Merge(err) {
551 if e, ok := err.(unexpectedJSONError); ok {
552 if e.value.Type() == json.EndArray {
553 // Done with list.
554 return nerr.E
555 }
556 }
557 return err
558 }
559 list.Append(val)
560 }
561 }
562 return nerr.E
563}
564
565// unmarshalMap unmarshals into given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700566func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800567 var nerr errors.NonFatal
568
Herbie Ong822de2d2019-03-27 13:16:23 -0700569 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800570 if !nerr.Merge(err) {
571 return err
572 }
573 if jval.Type() != json.StartObject {
574 return unexpectedJSONError{jval}
575 }
576
577 fields := fd.MessageType().Fields()
578 keyDesc := fields.ByNumber(1)
579 valDesc := fields.ByNumber(2)
580
581 // Determine ahead whether map entry is a scalar type or a message type in
582 // order to call the appropriate unmarshalMapValue func inside the for loop
583 // below.
584 unmarshalMapValue := func() (pref.Value, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700585 return o.unmarshalScalar(valDesc)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800586 }
587 switch valDesc.Kind() {
588 case pref.MessageKind, pref.GroupKind:
589 unmarshalMapValue = func() (pref.Value, error) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700590 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800591 m := mmap.NewMessage()
Herbie Ong822de2d2019-03-27 13:16:23 -0700592 if err := o.unmarshalMessage(m); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800593 return pref.Value{}, err
594 }
Herbie Onge63c4c42019-03-22 22:20:22 -0700595 return pref.ValueOf(m), nerr.E
Herbie Ongc96a79d2019-03-08 10:49:17 -0800596 }
597 }
598
599Loop:
600 for {
601 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700602 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800603 if !nerr.Merge(err) {
604 return err
605 }
606 switch jval.Type() {
607 default:
608 return unexpectedJSONError{jval}
609 case json.EndObject:
610 break Loop
611 case json.Name:
612 // Continue.
613 }
614
615 name, err := jval.Name()
616 if !nerr.Merge(err) {
617 return err
618 }
619
620 // Unmarshal field name.
621 pkey, err := unmarshalMapKey(name, keyDesc)
622 if !nerr.Merge(err) {
623 return err
624 }
625
626 // Check for duplicate field name.
627 if mmap.Has(pkey) {
628 return newError("duplicate map key %q", jval)
629 }
630
631 // Read and unmarshal field value.
632 pval, err := unmarshalMapValue()
633 if !nerr.Merge(err) {
634 return err
635 }
636
637 mmap.Set(pkey, pval)
638 }
639
640 return nerr.E
641}
642
643// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
644// integral or string type.
645func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
646 const b32 = 32
647 const b64 = 64
648 const base10 = 10
649
650 kind := fd.Kind()
651 switch kind {
652 case pref.StringKind:
653 return pref.ValueOf(name).MapKey(), nil
654
655 case pref.BoolKind:
656 switch name {
657 case "true":
658 return pref.ValueOf(true).MapKey(), nil
659 case "false":
660 return pref.ValueOf(false).MapKey(), nil
661 }
662 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
663
664 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
665 n, err := strconv.ParseInt(name, base10, b32)
666 if err != nil {
667 return pref.MapKey{}, err
668 }
669 return pref.ValueOf(int32(n)).MapKey(), nil
670
671 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
672 n, err := strconv.ParseInt(name, base10, b64)
673 if err != nil {
674 return pref.MapKey{}, err
675 }
676 return pref.ValueOf(int64(n)).MapKey(), nil
677
678 case pref.Uint32Kind, pref.Fixed32Kind:
679 n, err := strconv.ParseUint(name, base10, b32)
680 if err != nil {
681 return pref.MapKey{}, err
682 }
683 return pref.ValueOf(uint32(n)).MapKey(), nil
684
685 case pref.Uint64Kind, pref.Fixed64Kind:
686 n, err := strconv.ParseUint(name, base10, b64)
687 if err != nil {
688 return pref.MapKey{}, err
689 }
690 return pref.ValueOf(uint64(n)).MapKey(), nil
691 }
692
693 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
694}