blob: 816ba0a2e2978b04549b104744200bbcd677c5a5 [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
Herbie Ong329be5b2019-03-27 14:47:59 -070032 // AllowPartial accepts input for messages that will result in missing
33 // required fields. If AllowPartial is false (the default), Unmarshal will
34 // return error if there are any missing required fields.
35 AllowPartial bool
36
Herbie Onge52379a2019-03-15 18:00:19 -070037 // Resolver is the registry used for type lookups when unmarshaling extensions
38 // and processing Any. If Resolver is not set, unmarshaling will default to
39 // using protoregistry.GlobalTypes.
40 Resolver *protoregistry.Types
Herbie Ong822de2d2019-03-27 13:16:23 -070041
42 decoder *json.Decoder
Herbie Onge52379a2019-03-15 18:00:19 -070043}
Herbie Ongc96a79d2019-03-08 10:49:17 -080044
45// Unmarshal reads the given []byte and populates the given proto.Message using
46// options in UnmarshalOptions object. It will clear the message first before
47// setting the fields. If it returns an error, the given message may be
48// partially set.
49func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
50 mr := m.ProtoReflect()
51 // TODO: Determine if we would like to have an option for merging or only
52 // have merging behavior. We should at least be consistent with textproto
53 // marshaling.
54 resetMessage(mr)
55
Herbie Ong822de2d2019-03-27 13:16:23 -070056 if o.Resolver == nil {
57 o.Resolver = protoregistry.GlobalTypes
Herbie Onge52379a2019-03-15 18:00:19 -070058 }
Herbie Ong822de2d2019-03-27 13:16:23 -070059 o.decoder = json.NewDecoder(b)
Herbie Onge52379a2019-03-15 18:00:19 -070060
Herbie Ongc96a79d2019-03-08 10:49:17 -080061 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -070062 if err := o.unmarshalMessage(mr); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -080063 return err
64 }
65
66 // Check for EOF.
Herbie Ong822de2d2019-03-27 13:16:23 -070067 val, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -080068 if err != nil {
69 return err
70 }
71 if val.Type() != json.EOF {
72 return unexpectedJSONError{val}
73 }
74 return nerr.E
75}
76
77// resetMessage clears all fields of given protoreflect.Message.
78func resetMessage(m pref.Message) {
79 knownFields := m.KnownFields()
80 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
81 knownFields.Clear(num)
82 return true
83 })
84 unknownFields := m.UnknownFields()
85 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
86 unknownFields.Set(num, nil)
87 return true
88 })
89 extTypes := knownFields.ExtensionTypes()
90 extTypes.Range(func(xt pref.ExtensionType) bool {
91 extTypes.Remove(xt)
92 return true
93 })
94}
95
96// unexpectedJSONError is an error that contains the unexpected json.Value. This
Herbie Ong822de2d2019-03-27 13:16:23 -070097// is returned by methods to provide callers the read json.Value that it did not
98// expect.
Herbie Ongc96a79d2019-03-08 10:49:17 -080099// TODO: Consider moving this to internal/encoding/json for consistency with
100// errors that package returns.
101type unexpectedJSONError struct {
102 value json.Value
103}
104
105func (e unexpectedJSONError) Error() string {
106 return newError("unexpected value %s", e.value).Error()
107}
108
109// newError returns an error object. If one of the values passed in is of
110// json.Value type, it produces an error with position info.
111func newError(f string, x ...interface{}) error {
112 var hasValue bool
113 var line, column int
114 for i := 0; i < len(x); i++ {
115 if val, ok := x[i].(json.Value); ok {
116 line, column = val.Position()
117 hasValue = true
118 break
119 }
120 }
121 e := errors.New(f, x...)
122 if hasValue {
123 return errors.New("(line %d:%d): %v", line, column, e)
124 }
125 return e
126}
127
Herbie Ongc96a79d2019-03-08 10:49:17 -0800128// unmarshalMessage unmarshals a message into the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -0700129func (o UnmarshalOptions) unmarshalMessage(m pref.Message) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800130 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800131
Herbie Onge63c4c42019-03-22 22:20:22 -0700132 if isCustomType(m.Type().FullName()) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700133 return o.unmarshalCustomType(m)
Herbie Onge63c4c42019-03-22 22:20:22 -0700134 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800135
Herbie Ong822de2d2019-03-27 13:16:23 -0700136 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800137 if !nerr.Merge(err) {
138 return err
139 }
140 if jval.Type() != json.StartObject {
141 return unexpectedJSONError{jval}
142 }
143
Herbie Ong822de2d2019-03-27 13:16:23 -0700144 if err := o.unmarshalFields(m); !nerr.Merge(err) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700145 return err
146 }
147
148 return nerr.E
149}
150
151// unmarshalFields unmarshals the fields into the given protoreflect.Message.
Herbie Ong822de2d2019-03-27 13:16:23 -0700152func (o UnmarshalOptions) unmarshalFields(m pref.Message) error {
Herbie Onge63c4c42019-03-22 22:20:22 -0700153 var nerr errors.NonFatal
154 var reqNums set.Ints
155 var seenNums set.Ints
156
157 msgType := m.Type()
158 knownFields := m.KnownFields()
159 fieldDescs := msgType.Fields()
160 xtTypes := knownFields.ExtensionTypes()
161
Herbie Ongc96a79d2019-03-08 10:49:17 -0800162Loop:
163 for {
164 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700165 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800166 if !nerr.Merge(err) {
167 return err
168 }
169 switch jval.Type() {
170 default:
171 return unexpectedJSONError{jval}
172 case json.EndObject:
173 break Loop
174 case json.Name:
175 // Continue below.
176 }
177
178 name, err := jval.Name()
179 if !nerr.Merge(err) {
180 return err
181 }
182
Herbie Onge52379a2019-03-15 18:00:19 -0700183 // Get the FieldDescriptor.
184 var fd pref.FieldDescriptor
185 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
186 // Only extension names are in [name] format.
187 xtName := pref.FullName(name[1 : len(name)-1])
188 xt := xtTypes.ByName(xtName)
189 if xt == nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700190 xt, err = o.findExtension(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700191 if err != nil && err != protoregistry.NotFound {
192 return errors.New("unable to resolve [%v]: %v", xtName, err)
193 }
194 if xt != nil {
195 xtTypes.Register(xt)
196 }
197 }
198 fd = xt
199 } else {
200 // The name can either be the JSON name or the proto field name.
201 fd = fieldDescs.ByJSONName(name)
202 if fd == nil {
203 fd = fieldDescs.ByName(pref.Name(name))
204 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800205 }
206
207 if fd == nil {
208 // Field is unknown.
209 // TODO: Provide option to ignore unknown message fields.
210 return newError("%v contains unknown field %s", msgType.FullName(), jval)
211 }
212
213 // Do not allow duplicate fields.
214 num := uint64(fd.Number())
215 if seenNums.Has(num) {
216 return newError("%v contains repeated field %s", msgType.FullName(), jval)
217 }
218 seenNums.Set(num)
219
Herbie Onge63c4c42019-03-22 22:20:22 -0700220 // No need to set values for JSON null unless the field type is
221 // google.protobuf.Value.
Herbie Ong822de2d2019-03-27 13:16:23 -0700222 if o.decoder.Peek() == json.Null && !isKnownValue(fd) {
223 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800224 continue
225 }
226
227 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
228 // Map or list fields have cardinality of repeated.
Herbie Ong822de2d2019-03-27 13:16:23 -0700229 if err := o.unmarshalRepeated(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 } else {
233 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700234 if err := o.unmarshalSingular(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800235 return errors.New("%v|%q: %v", fd.FullName(), name, err)
236 }
Herbie Ong329be5b2019-03-27 14:47:59 -0700237 if !o.AllowPartial && cardinality == pref.Required {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800238 reqNums.Set(num)
239 }
240 }
241 }
242
Herbie Ong329be5b2019-03-27 14:47:59 -0700243 if !o.AllowPartial {
244 // Check for any missing required fields.
245 allReqNums := msgType.RequiredNumbers()
246 if reqNums.Len() != allReqNums.Len() {
247 for i := 0; i < allReqNums.Len(); i++ {
248 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
249 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
250 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800251 }
252 }
253 }
254
255 return nerr.E
256}
257
Herbie Onge52379a2019-03-15 18:00:19 -0700258// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700259func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
260 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700261 if err == nil {
262 return xt, nil
263 }
264
265 // Check if this is a MessageSet extension field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700266 xt, err = o.Resolver.FindExtensionByName(xtName + ".message_set_extension")
Herbie Onge52379a2019-03-15 18:00:19 -0700267 if err == nil && isMessageSetExtension(xt) {
268 return xt, nil
269 }
270 return nil, protoregistry.NotFound
271}
272
Herbie Ongc96a79d2019-03-08 10:49:17 -0800273// unmarshalSingular unmarshals to the non-repeated field specified by the given
274// FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700275func (o UnmarshalOptions) unmarshalSingular(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800276 var val pref.Value
277 var err error
278 num := fd.Number()
279
280 switch fd.Kind() {
281 case pref.MessageKind, pref.GroupKind:
282 m := knownFields.NewMessage(num)
Herbie Ong822de2d2019-03-27 13:16:23 -0700283 err = o.unmarshalMessage(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800284 val = pref.ValueOf(m)
285 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700286 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800287 }
288
289 var nerr errors.NonFatal
290 if !nerr.Merge(err) {
291 return err
292 }
293 knownFields.Set(num, val)
294 return nerr.E
295}
296
297// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
298// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700299func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800300 const b32 int = 32
301 const b64 int = 64
302
303 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700304 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800305 if !nerr.Merge(err) {
306 return pref.Value{}, err
307 }
308
309 kind := fd.Kind()
310 switch kind {
311 case pref.BoolKind:
312 return unmarshalBool(jval)
313
314 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
315 return unmarshalInt(jval, b32)
316
317 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
318 return unmarshalInt(jval, b64)
319
320 case pref.Uint32Kind, pref.Fixed32Kind:
321 return unmarshalUint(jval, b32)
322
323 case pref.Uint64Kind, pref.Fixed64Kind:
324 return unmarshalUint(jval, b64)
325
326 case pref.FloatKind:
327 return unmarshalFloat(jval, b32)
328
329 case pref.DoubleKind:
330 return unmarshalFloat(jval, b64)
331
332 case pref.StringKind:
333 pval, err := unmarshalString(jval)
334 if !nerr.Merge(err) {
335 return pval, err
336 }
337 return pval, nerr.E
338
339 case pref.BytesKind:
340 return unmarshalBytes(jval)
341
342 case pref.EnumKind:
343 return unmarshalEnum(jval, fd)
344 }
345
346 panic(fmt.Sprintf("invalid scalar kind %v", kind))
347}
348
349func unmarshalBool(jval json.Value) (pref.Value, error) {
350 if jval.Type() != json.Bool {
351 return pref.Value{}, unexpectedJSONError{jval}
352 }
353 b, err := jval.Bool()
354 return pref.ValueOf(b), err
355}
356
357func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
358 switch jval.Type() {
359 case json.Number:
360 return getInt(jval, bitSize)
361
362 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700363 // Decode number from string.
364 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800365 var nerr errors.NonFatal
366 jval, err := dec.Read()
367 if !nerr.Merge(err) {
368 return pref.Value{}, err
369 }
370 return getInt(jval, bitSize)
371 }
372 return pref.Value{}, unexpectedJSONError{jval}
373}
374
375func getInt(jval json.Value, bitSize int) (pref.Value, error) {
376 n, err := jval.Int(bitSize)
377 if err != nil {
378 return pref.Value{}, err
379 }
380 if bitSize == 32 {
381 return pref.ValueOf(int32(n)), nil
382 }
383 return pref.ValueOf(n), nil
384}
385
386func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
387 switch jval.Type() {
388 case json.Number:
389 return getUint(jval, bitSize)
390
391 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700392 // Decode number from string.
393 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800394 var nerr errors.NonFatal
395 jval, err := dec.Read()
396 if !nerr.Merge(err) {
397 return pref.Value{}, err
398 }
399 return getUint(jval, bitSize)
400 }
401 return pref.Value{}, unexpectedJSONError{jval}
402}
403
404func getUint(jval json.Value, bitSize int) (pref.Value, error) {
405 n, err := jval.Uint(bitSize)
406 if err != nil {
407 return pref.Value{}, err
408 }
409 if bitSize == 32 {
410 return pref.ValueOf(uint32(n)), nil
411 }
412 return pref.ValueOf(n), nil
413}
414
415func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
416 switch jval.Type() {
417 case json.Number:
418 return getFloat(jval, bitSize)
419
420 case json.String:
421 s := jval.String()
422 switch s {
423 case "NaN":
424 if bitSize == 32 {
425 return pref.ValueOf(float32(math.NaN())), nil
426 }
427 return pref.ValueOf(math.NaN()), nil
428 case "Infinity":
429 if bitSize == 32 {
430 return pref.ValueOf(float32(math.Inf(+1))), nil
431 }
432 return pref.ValueOf(math.Inf(+1)), nil
433 case "-Infinity":
434 if bitSize == 32 {
435 return pref.ValueOf(float32(math.Inf(-1))), nil
436 }
437 return pref.ValueOf(math.Inf(-1)), nil
438 }
Herbie Onge52379a2019-03-15 18:00:19 -0700439 // Decode number from string.
440 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800441 var nerr errors.NonFatal
442 jval, err := dec.Read()
443 if !nerr.Merge(err) {
444 return pref.Value{}, err
445 }
446 return getFloat(jval, bitSize)
447 }
448 return pref.Value{}, unexpectedJSONError{jval}
449}
450
451func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
452 n, err := jval.Float(bitSize)
453 if err != nil {
454 return pref.Value{}, err
455 }
456 if bitSize == 32 {
457 return pref.ValueOf(float32(n)), nil
458 }
459 return pref.ValueOf(n), nil
460}
461
462func unmarshalString(jval json.Value) (pref.Value, error) {
463 if jval.Type() != json.String {
464 return pref.Value{}, unexpectedJSONError{jval}
465 }
466 return pref.ValueOf(jval.String()), nil
467}
468
469func unmarshalBytes(jval json.Value) (pref.Value, error) {
470 if jval.Type() != json.String {
471 return pref.Value{}, unexpectedJSONError{jval}
472 }
473
474 s := jval.String()
475 enc := base64.StdEncoding
476 if strings.ContainsAny(s, "-_") {
477 enc = base64.URLEncoding
478 }
479 if len(s)%4 != 0 {
480 enc = enc.WithPadding(base64.NoPadding)
481 }
482 b, err := enc.DecodeString(s)
483 if err != nil {
484 return pref.Value{}, err
485 }
486 return pref.ValueOf(b), nil
487}
488
489func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
490 switch jval.Type() {
491 case json.String:
492 // Lookup EnumNumber based on name.
493 s := jval.String()
494 if enumVal := fd.EnumType().Values().ByName(pref.Name(s)); enumVal != nil {
495 return pref.ValueOf(enumVal.Number()), nil
496 }
497 return pref.Value{}, newError("invalid enum value %q", jval)
498
499 case json.Number:
500 n, err := jval.Int(32)
501 if err != nil {
502 return pref.Value{}, err
503 }
504 return pref.ValueOf(pref.EnumNumber(n)), nil
505 }
506
507 return pref.Value{}, unexpectedJSONError{jval}
508}
509
510// unmarshalRepeated unmarshals into a repeated field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700511func (o UnmarshalOptions) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800512 var nerr errors.NonFatal
513 num := fd.Number()
514 val := knownFields.Get(num)
515 if !fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700516 if err := o.unmarshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800517 return err
518 }
519 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700520 if err := o.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800521 return err
522 }
523 }
524 return nerr.E
525}
526
527// unmarshalList unmarshals into given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700528func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800529 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700530 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800531 if !nerr.Merge(err) {
532 return err
533 }
534 if jval.Type() != json.StartArray {
535 return unexpectedJSONError{jval}
536 }
537
538 switch fd.Kind() {
539 case pref.MessageKind, pref.GroupKind:
540 for {
541 m := list.NewMessage()
Herbie Ong822de2d2019-03-27 13:16:23 -0700542 err := o.unmarshalMessage(m)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800543 if !nerr.Merge(err) {
544 if e, ok := err.(unexpectedJSONError); ok {
545 if e.value.Type() == json.EndArray {
546 // Done with list.
547 return nerr.E
548 }
549 }
550 return err
551 }
552 list.Append(pref.ValueOf(m))
553 }
554 default:
555 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700556 val, err := o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800557 if !nerr.Merge(err) {
558 if e, ok := err.(unexpectedJSONError); ok {
559 if e.value.Type() == json.EndArray {
560 // Done with list.
561 return nerr.E
562 }
563 }
564 return err
565 }
566 list.Append(val)
567 }
568 }
569 return nerr.E
570}
571
572// unmarshalMap unmarshals into given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700573func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800574 var nerr errors.NonFatal
575
Herbie Ong822de2d2019-03-27 13:16:23 -0700576 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800577 if !nerr.Merge(err) {
578 return err
579 }
580 if jval.Type() != json.StartObject {
581 return unexpectedJSONError{jval}
582 }
583
584 fields := fd.MessageType().Fields()
585 keyDesc := fields.ByNumber(1)
586 valDesc := fields.ByNumber(2)
587
588 // Determine ahead whether map entry is a scalar type or a message type in
589 // order to call the appropriate unmarshalMapValue func inside the for loop
590 // below.
591 unmarshalMapValue := func() (pref.Value, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700592 return o.unmarshalScalar(valDesc)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800593 }
594 switch valDesc.Kind() {
595 case pref.MessageKind, pref.GroupKind:
596 unmarshalMapValue = func() (pref.Value, error) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700597 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800598 m := mmap.NewMessage()
Herbie Ong822de2d2019-03-27 13:16:23 -0700599 if err := o.unmarshalMessage(m); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800600 return pref.Value{}, err
601 }
Herbie Onge63c4c42019-03-22 22:20:22 -0700602 return pref.ValueOf(m), nerr.E
Herbie Ongc96a79d2019-03-08 10:49:17 -0800603 }
604 }
605
606Loop:
607 for {
608 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700609 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800610 if !nerr.Merge(err) {
611 return err
612 }
613 switch jval.Type() {
614 default:
615 return unexpectedJSONError{jval}
616 case json.EndObject:
617 break Loop
618 case json.Name:
619 // Continue.
620 }
621
622 name, err := jval.Name()
623 if !nerr.Merge(err) {
624 return err
625 }
626
627 // Unmarshal field name.
628 pkey, err := unmarshalMapKey(name, keyDesc)
629 if !nerr.Merge(err) {
630 return err
631 }
632
633 // Check for duplicate field name.
634 if mmap.Has(pkey) {
635 return newError("duplicate map key %q", jval)
636 }
637
638 // Read and unmarshal field value.
639 pval, err := unmarshalMapValue()
640 if !nerr.Merge(err) {
641 return err
642 }
643
644 mmap.Set(pkey, pval)
645 }
646
647 return nerr.E
648}
649
650// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
651// integral or string type.
652func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
653 const b32 = 32
654 const b64 = 64
655 const base10 = 10
656
657 kind := fd.Kind()
658 switch kind {
659 case pref.StringKind:
660 return pref.ValueOf(name).MapKey(), nil
661
662 case pref.BoolKind:
663 switch name {
664 case "true":
665 return pref.ValueOf(true).MapKey(), nil
666 case "false":
667 return pref.ValueOf(false).MapKey(), nil
668 }
669 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
670
671 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
672 n, err := strconv.ParseInt(name, base10, b32)
673 if err != nil {
674 return pref.MapKey{}, err
675 }
676 return pref.ValueOf(int32(n)).MapKey(), nil
677
678 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
679 n, err := strconv.ParseInt(name, base10, b64)
680 if err != nil {
681 return pref.MapKey{}, err
682 }
683 return pref.ValueOf(int64(n)).MapKey(), nil
684
685 case pref.Uint32Kind, pref.Fixed32Kind:
686 n, err := strconv.ParseUint(name, base10, b32)
687 if err != nil {
688 return pref.MapKey{}, err
689 }
690 return pref.ValueOf(uint32(n)).MapKey(), nil
691
692 case pref.Uint64Kind, pref.Fixed64Kind:
693 n, err := strconv.ParseUint(name, base10, b64)
694 if err != nil {
695 return pref.MapKey{}, err
696 }
697 return pref.ValueOf(uint64(n)).MapKey(), nil
698 }
699
700 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
701}