blob: 7655054d5ee416c34a2931768b192fb6d7a63ccb [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 Ong8ac9dd22019-03-27 12:20:50 -070062 if err := o.unmarshalMessage(mr, false); !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 Ong8ac9dd22019-03-27 12:20:50 -0700129func (o UnmarshalOptions) unmarshalMessage(m pref.Message, skipTypeURL bool) 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 Ong8ac9dd22019-03-27 12:20:50 -0700144 if err := o.unmarshalFields(m, skipTypeURL); !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 Ong8ac9dd22019-03-27 12:20:50 -0700152func (o UnmarshalOptions) unmarshalFields(m pref.Message, skipTypeURL bool) 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 }
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700182 // Unmarshaling a non-custom embedded message in Any will contain the
183 // JSON field "@type" which should be skipped because it is not a field
184 // of the embedded message, but simply an artifact of the Any format.
185 if skipTypeURL && name == "@type" {
186 o.decoder.Read()
187 continue
188 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800189
Herbie Onge52379a2019-03-15 18:00:19 -0700190 // Get the FieldDescriptor.
191 var fd pref.FieldDescriptor
192 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
193 // Only extension names are in [name] format.
194 xtName := pref.FullName(name[1 : len(name)-1])
195 xt := xtTypes.ByName(xtName)
196 if xt == nil {
Herbie Ong822de2d2019-03-27 13:16:23 -0700197 xt, err = o.findExtension(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700198 if err != nil && err != protoregistry.NotFound {
199 return errors.New("unable to resolve [%v]: %v", xtName, err)
200 }
201 if xt != nil {
202 xtTypes.Register(xt)
203 }
204 }
205 fd = xt
206 } else {
207 // The name can either be the JSON name or the proto field name.
208 fd = fieldDescs.ByJSONName(name)
209 if fd == nil {
210 fd = fieldDescs.ByName(pref.Name(name))
211 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800212 }
213
214 if fd == nil {
215 // Field is unknown.
216 // TODO: Provide option to ignore unknown message fields.
217 return newError("%v contains unknown field %s", msgType.FullName(), jval)
218 }
219
220 // Do not allow duplicate fields.
221 num := uint64(fd.Number())
222 if seenNums.Has(num) {
223 return newError("%v contains repeated field %s", msgType.FullName(), jval)
224 }
225 seenNums.Set(num)
226
Herbie Onge63c4c42019-03-22 22:20:22 -0700227 // No need to set values for JSON null unless the field type is
Herbie Ong300b9fe2019-03-29 15:42:20 -0700228 // google.protobuf.Value or google.protobuf.NullValue.
229 if o.decoder.Peek() == json.Null && !isKnownValue(fd) && !isNullValue(fd) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700230 o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800231 continue
232 }
233
234 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
235 // Map or list fields have cardinality of repeated.
Herbie Ong822de2d2019-03-27 13:16:23 -0700236 if err := o.unmarshalRepeated(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800237 return errors.New("%v|%q: %v", fd.FullName(), name, err)
238 }
239 } else {
240 // Required or optional fields.
Herbie Ong822de2d2019-03-27 13:16:23 -0700241 if err := o.unmarshalSingular(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800242 return errors.New("%v|%q: %v", fd.FullName(), name, err)
243 }
Herbie Ong329be5b2019-03-27 14:47:59 -0700244 if !o.AllowPartial && cardinality == pref.Required {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800245 reqNums.Set(num)
246 }
247 }
248 }
249
Herbie Ong329be5b2019-03-27 14:47:59 -0700250 if !o.AllowPartial {
251 // Check for any missing required fields.
252 allReqNums := msgType.RequiredNumbers()
253 if reqNums.Len() != allReqNums.Len() {
254 for i := 0; i < allReqNums.Len(); i++ {
255 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
256 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
257 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800258 }
259 }
260 }
261
262 return nerr.E
263}
264
Herbie Onge52379a2019-03-15 18:00:19 -0700265// findExtension returns protoreflect.ExtensionType from the resolver if found.
Herbie Ong822de2d2019-03-27 13:16:23 -0700266func (o UnmarshalOptions) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
267 xt, err := o.Resolver.FindExtensionByName(xtName)
Herbie Onge52379a2019-03-15 18:00:19 -0700268 if err == nil {
269 return xt, nil
270 }
271
272 // Check if this is a MessageSet extension field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700273 xt, err = o.Resolver.FindExtensionByName(xtName + ".message_set_extension")
Herbie Onge52379a2019-03-15 18:00:19 -0700274 if err == nil && isMessageSetExtension(xt) {
275 return xt, nil
276 }
277 return nil, protoregistry.NotFound
278}
279
Herbie Ong300b9fe2019-03-29 15:42:20 -0700280func isKnownValue(fd pref.FieldDescriptor) bool {
281 md := fd.MessageType()
282 return md != nil && md.FullName() == "google.protobuf.Value"
283}
284
285func isNullValue(fd pref.FieldDescriptor) bool {
286 ed := fd.EnumType()
287 return ed != nil && ed.FullName() == "google.protobuf.NullValue"
288}
289
Herbie Ongc96a79d2019-03-08 10:49:17 -0800290// unmarshalSingular unmarshals to the non-repeated field specified by the given
291// FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700292func (o UnmarshalOptions) unmarshalSingular(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800293 var val pref.Value
294 var err error
295 num := fd.Number()
296
297 switch fd.Kind() {
298 case pref.MessageKind, pref.GroupKind:
299 m := knownFields.NewMessage(num)
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700300 err = o.unmarshalMessage(m, false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800301 val = pref.ValueOf(m)
302 default:
Herbie Ong822de2d2019-03-27 13:16:23 -0700303 val, err = o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800304 }
305
306 var nerr errors.NonFatal
307 if !nerr.Merge(err) {
308 return err
309 }
310 knownFields.Set(num, val)
311 return nerr.E
312}
313
314// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
315// the given FieldDescriptor.
Herbie Ong822de2d2019-03-27 13:16:23 -0700316func (o UnmarshalOptions) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800317 const b32 int = 32
318 const b64 int = 64
319
320 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700321 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800322 if !nerr.Merge(err) {
323 return pref.Value{}, err
324 }
325
326 kind := fd.Kind()
327 switch kind {
328 case pref.BoolKind:
329 return unmarshalBool(jval)
330
331 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
332 return unmarshalInt(jval, b32)
333
334 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
335 return unmarshalInt(jval, b64)
336
337 case pref.Uint32Kind, pref.Fixed32Kind:
338 return unmarshalUint(jval, b32)
339
340 case pref.Uint64Kind, pref.Fixed64Kind:
341 return unmarshalUint(jval, b64)
342
343 case pref.FloatKind:
344 return unmarshalFloat(jval, b32)
345
346 case pref.DoubleKind:
347 return unmarshalFloat(jval, b64)
348
349 case pref.StringKind:
350 pval, err := unmarshalString(jval)
351 if !nerr.Merge(err) {
352 return pval, err
353 }
354 return pval, nerr.E
355
356 case pref.BytesKind:
357 return unmarshalBytes(jval)
358
359 case pref.EnumKind:
360 return unmarshalEnum(jval, fd)
361 }
362
363 panic(fmt.Sprintf("invalid scalar kind %v", kind))
364}
365
366func unmarshalBool(jval json.Value) (pref.Value, error) {
367 if jval.Type() != json.Bool {
368 return pref.Value{}, unexpectedJSONError{jval}
369 }
370 b, err := jval.Bool()
371 return pref.ValueOf(b), err
372}
373
374func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
375 switch jval.Type() {
376 case json.Number:
377 return getInt(jval, bitSize)
378
379 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700380 // Decode number from string.
381 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800382 var nerr errors.NonFatal
383 jval, err := dec.Read()
384 if !nerr.Merge(err) {
385 return pref.Value{}, err
386 }
387 return getInt(jval, bitSize)
388 }
389 return pref.Value{}, unexpectedJSONError{jval}
390}
391
392func getInt(jval json.Value, bitSize int) (pref.Value, error) {
393 n, err := jval.Int(bitSize)
394 if err != nil {
395 return pref.Value{}, err
396 }
397 if bitSize == 32 {
398 return pref.ValueOf(int32(n)), nil
399 }
400 return pref.ValueOf(n), nil
401}
402
403func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
404 switch jval.Type() {
405 case json.Number:
406 return getUint(jval, bitSize)
407
408 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700409 // Decode number from string.
410 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800411 var nerr errors.NonFatal
412 jval, err := dec.Read()
413 if !nerr.Merge(err) {
414 return pref.Value{}, err
415 }
416 return getUint(jval, bitSize)
417 }
418 return pref.Value{}, unexpectedJSONError{jval}
419}
420
421func getUint(jval json.Value, bitSize int) (pref.Value, error) {
422 n, err := jval.Uint(bitSize)
423 if err != nil {
424 return pref.Value{}, err
425 }
426 if bitSize == 32 {
427 return pref.ValueOf(uint32(n)), nil
428 }
429 return pref.ValueOf(n), nil
430}
431
432func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
433 switch jval.Type() {
434 case json.Number:
435 return getFloat(jval, bitSize)
436
437 case json.String:
438 s := jval.String()
439 switch s {
440 case "NaN":
441 if bitSize == 32 {
442 return pref.ValueOf(float32(math.NaN())), nil
443 }
444 return pref.ValueOf(math.NaN()), nil
445 case "Infinity":
446 if bitSize == 32 {
447 return pref.ValueOf(float32(math.Inf(+1))), nil
448 }
449 return pref.ValueOf(math.Inf(+1)), nil
450 case "-Infinity":
451 if bitSize == 32 {
452 return pref.ValueOf(float32(math.Inf(-1))), nil
453 }
454 return pref.ValueOf(math.Inf(-1)), nil
455 }
Herbie Onge52379a2019-03-15 18:00:19 -0700456 // Decode number from string.
457 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800458 var nerr errors.NonFatal
459 jval, err := dec.Read()
460 if !nerr.Merge(err) {
461 return pref.Value{}, err
462 }
463 return getFloat(jval, bitSize)
464 }
465 return pref.Value{}, unexpectedJSONError{jval}
466}
467
468func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
469 n, err := jval.Float(bitSize)
470 if err != nil {
471 return pref.Value{}, err
472 }
473 if bitSize == 32 {
474 return pref.ValueOf(float32(n)), nil
475 }
476 return pref.ValueOf(n), nil
477}
478
479func unmarshalString(jval json.Value) (pref.Value, error) {
480 if jval.Type() != json.String {
481 return pref.Value{}, unexpectedJSONError{jval}
482 }
483 return pref.ValueOf(jval.String()), nil
484}
485
486func unmarshalBytes(jval json.Value) (pref.Value, error) {
487 if jval.Type() != json.String {
488 return pref.Value{}, unexpectedJSONError{jval}
489 }
490
491 s := jval.String()
492 enc := base64.StdEncoding
493 if strings.ContainsAny(s, "-_") {
494 enc = base64.URLEncoding
495 }
496 if len(s)%4 != 0 {
497 enc = enc.WithPadding(base64.NoPadding)
498 }
499 b, err := enc.DecodeString(s)
500 if err != nil {
501 return pref.Value{}, err
502 }
503 return pref.ValueOf(b), nil
504}
505
506func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
507 switch jval.Type() {
508 case json.String:
509 // Lookup EnumNumber based on name.
510 s := jval.String()
511 if enumVal := fd.EnumType().Values().ByName(pref.Name(s)); enumVal != nil {
512 return pref.ValueOf(enumVal.Number()), nil
513 }
514 return pref.Value{}, newError("invalid enum value %q", jval)
515
516 case json.Number:
517 n, err := jval.Int(32)
518 if err != nil {
519 return pref.Value{}, err
520 }
521 return pref.ValueOf(pref.EnumNumber(n)), nil
Herbie Ong300b9fe2019-03-29 15:42:20 -0700522
523 case json.Null:
524 // This is only valid for google.protobuf.NullValue.
525 if isNullValue(fd) {
526 return pref.ValueOf(pref.EnumNumber(0)), nil
527 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800528 }
529
530 return pref.Value{}, unexpectedJSONError{jval}
531}
532
533// unmarshalRepeated unmarshals into a repeated field.
Herbie Ong822de2d2019-03-27 13:16:23 -0700534func (o UnmarshalOptions) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800535 var nerr errors.NonFatal
536 num := fd.Number()
537 val := knownFields.Get(num)
538 if !fd.IsMap() {
Herbie Ong822de2d2019-03-27 13:16:23 -0700539 if err := o.unmarshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800540 return err
541 }
542 } else {
Herbie Ong822de2d2019-03-27 13:16:23 -0700543 if err := o.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800544 return err
545 }
546 }
547 return nerr.E
548}
549
550// unmarshalList unmarshals into given protoreflect.List.
Herbie Ong822de2d2019-03-27 13:16:23 -0700551func (o UnmarshalOptions) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800552 var nerr errors.NonFatal
Herbie Ong822de2d2019-03-27 13:16:23 -0700553 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800554 if !nerr.Merge(err) {
555 return err
556 }
557 if jval.Type() != json.StartArray {
558 return unexpectedJSONError{jval}
559 }
560
561 switch fd.Kind() {
562 case pref.MessageKind, pref.GroupKind:
563 for {
564 m := list.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700565 err := o.unmarshalMessage(m, false)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800566 if !nerr.Merge(err) {
567 if e, ok := err.(unexpectedJSONError); ok {
568 if e.value.Type() == json.EndArray {
569 // Done with list.
570 return nerr.E
571 }
572 }
573 return err
574 }
575 list.Append(pref.ValueOf(m))
576 }
577 default:
578 for {
Herbie Ong822de2d2019-03-27 13:16:23 -0700579 val, err := o.unmarshalScalar(fd)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800580 if !nerr.Merge(err) {
581 if e, ok := err.(unexpectedJSONError); ok {
582 if e.value.Type() == json.EndArray {
583 // Done with list.
584 return nerr.E
585 }
586 }
587 return err
588 }
589 list.Append(val)
590 }
591 }
592 return nerr.E
593}
594
595// unmarshalMap unmarshals into given protoreflect.Map.
Herbie Ong822de2d2019-03-27 13:16:23 -0700596func (o UnmarshalOptions) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800597 var nerr errors.NonFatal
598
Herbie Ong822de2d2019-03-27 13:16:23 -0700599 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800600 if !nerr.Merge(err) {
601 return err
602 }
603 if jval.Type() != json.StartObject {
604 return unexpectedJSONError{jval}
605 }
606
607 fields := fd.MessageType().Fields()
608 keyDesc := fields.ByNumber(1)
609 valDesc := fields.ByNumber(2)
610
611 // Determine ahead whether map entry is a scalar type or a message type in
612 // order to call the appropriate unmarshalMapValue func inside the for loop
613 // below.
614 unmarshalMapValue := func() (pref.Value, error) {
Herbie Ong822de2d2019-03-27 13:16:23 -0700615 return o.unmarshalScalar(valDesc)
Herbie Ongc96a79d2019-03-08 10:49:17 -0800616 }
617 switch valDesc.Kind() {
618 case pref.MessageKind, pref.GroupKind:
619 unmarshalMapValue = func() (pref.Value, error) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700620 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800621 m := mmap.NewMessage()
Herbie Ong8ac9dd22019-03-27 12:20:50 -0700622 if err := o.unmarshalMessage(m, false); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800623 return pref.Value{}, err
624 }
Herbie Onge63c4c42019-03-22 22:20:22 -0700625 return pref.ValueOf(m), nerr.E
Herbie Ongc96a79d2019-03-08 10:49:17 -0800626 }
627 }
628
629Loop:
630 for {
631 // Read field name.
Herbie Ong822de2d2019-03-27 13:16:23 -0700632 jval, err := o.decoder.Read()
Herbie Ongc96a79d2019-03-08 10:49:17 -0800633 if !nerr.Merge(err) {
634 return err
635 }
636 switch jval.Type() {
637 default:
638 return unexpectedJSONError{jval}
639 case json.EndObject:
640 break Loop
641 case json.Name:
642 // Continue.
643 }
644
645 name, err := jval.Name()
646 if !nerr.Merge(err) {
647 return err
648 }
649
650 // Unmarshal field name.
651 pkey, err := unmarshalMapKey(name, keyDesc)
652 if !nerr.Merge(err) {
653 return err
654 }
655
656 // Check for duplicate field name.
657 if mmap.Has(pkey) {
658 return newError("duplicate map key %q", jval)
659 }
660
661 // Read and unmarshal field value.
662 pval, err := unmarshalMapValue()
663 if !nerr.Merge(err) {
664 return err
665 }
666
667 mmap.Set(pkey, pval)
668 }
669
670 return nerr.E
671}
672
673// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
674// integral or string type.
675func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
676 const b32 = 32
677 const b64 = 64
678 const base10 = 10
679
680 kind := fd.Kind()
681 switch kind {
682 case pref.StringKind:
683 return pref.ValueOf(name).MapKey(), nil
684
685 case pref.BoolKind:
686 switch name {
687 case "true":
688 return pref.ValueOf(true).MapKey(), nil
689 case "false":
690 return pref.ValueOf(false).MapKey(), nil
691 }
692 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
693
694 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
695 n, err := strconv.ParseInt(name, base10, b32)
696 if err != nil {
697 return pref.MapKey{}, err
698 }
699 return pref.ValueOf(int32(n)).MapKey(), nil
700
701 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
702 n, err := strconv.ParseInt(name, base10, b64)
703 if err != nil {
704 return pref.MapKey{}, err
705 }
706 return pref.ValueOf(int64(n)).MapKey(), nil
707
708 case pref.Uint32Kind, pref.Fixed32Kind:
709 n, err := strconv.ParseUint(name, base10, b32)
710 if err != nil {
711 return pref.MapKey{}, err
712 }
713 return pref.ValueOf(uint32(n)).MapKey(), nil
714
715 case pref.Uint64Kind, pref.Fixed64Kind:
716 n, err := strconv.ParseUint(name, base10, b64)
717 if err != nil {
718 return pref.MapKey{}, err
719 }
720 return pref.ValueOf(uint64(n)).MapKey(), nil
721 }
722
723 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
724}