blob: 8436c386d13ecac264ab55f4aff71a2c9de1cb07 [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
36}
Herbie Ongc96a79d2019-03-08 10:49:17 -080037
38// Unmarshal reads the given []byte and populates the given proto.Message using
39// options in UnmarshalOptions object. It will clear the message first before
40// setting the fields. If it returns an error, the given message may be
41// partially set.
42func (o UnmarshalOptions) Unmarshal(m proto.Message, b []byte) error {
43 mr := m.ProtoReflect()
44 // TODO: Determine if we would like to have an option for merging or only
45 // have merging behavior. We should at least be consistent with textproto
46 // marshaling.
47 resetMessage(mr)
48
Herbie Onge52379a2019-03-15 18:00:19 -070049 resolver := o.Resolver
50 if resolver == nil {
51 resolver = protoregistry.GlobalTypes
52 }
53
54 dec := decoder{
55 Decoder: json.NewDecoder(b),
56 resolver: resolver,
57 }
Herbie Ongc96a79d2019-03-08 10:49:17 -080058 var nerr errors.NonFatal
59 if err := dec.unmarshalMessage(mr); !nerr.Merge(err) {
60 return err
61 }
62
63 // Check for EOF.
64 val, err := dec.Read()
65 if err != nil {
66 return err
67 }
68 if val.Type() != json.EOF {
69 return unexpectedJSONError{val}
70 }
71 return nerr.E
72}
73
74// resetMessage clears all fields of given protoreflect.Message.
75func resetMessage(m pref.Message) {
76 knownFields := m.KnownFields()
77 knownFields.Range(func(num pref.FieldNumber, _ pref.Value) bool {
78 knownFields.Clear(num)
79 return true
80 })
81 unknownFields := m.UnknownFields()
82 unknownFields.Range(func(num pref.FieldNumber, _ pref.RawFields) bool {
83 unknownFields.Set(num, nil)
84 return true
85 })
86 extTypes := knownFields.ExtensionTypes()
87 extTypes.Range(func(xt pref.ExtensionType) bool {
88 extTypes.Remove(xt)
89 return true
90 })
91}
92
93// unexpectedJSONError is an error that contains the unexpected json.Value. This
94// is used by decoder methods to provide callers the read json.Value that it
95// did not expect.
96// TODO: Consider moving this to internal/encoding/json for consistency with
97// errors that package returns.
98type unexpectedJSONError struct {
99 value json.Value
100}
101
102func (e unexpectedJSONError) Error() string {
103 return newError("unexpected value %s", e.value).Error()
104}
105
106// newError returns an error object. If one of the values passed in is of
107// json.Value type, it produces an error with position info.
108func newError(f string, x ...interface{}) error {
109 var hasValue bool
110 var line, column int
111 for i := 0; i < len(x); i++ {
112 if val, ok := x[i].(json.Value); ok {
113 line, column = val.Position()
114 hasValue = true
115 break
116 }
117 }
118 e := errors.New(f, x...)
119 if hasValue {
120 return errors.New("(line %d:%d): %v", line, column, e)
121 }
122 return e
123}
124
125// decoder decodes JSON into protoreflect values.
126type decoder struct {
127 *json.Decoder
Herbie Onge52379a2019-03-15 18:00:19 -0700128 resolver *protoregistry.Types
Herbie Ongc96a79d2019-03-08 10:49:17 -0800129}
130
131// unmarshalMessage unmarshals a message into the given protoreflect.Message.
132func (d decoder) unmarshalMessage(m pref.Message) error {
133 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800134
Herbie Onge63c4c42019-03-22 22:20:22 -0700135 if isCustomType(m.Type().FullName()) {
136 return d.unmarshalCustomType(m)
137 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800138
139 jval, err := d.Read()
140 if !nerr.Merge(err) {
141 return err
142 }
143 if jval.Type() != json.StartObject {
144 return unexpectedJSONError{jval}
145 }
146
Herbie Onge63c4c42019-03-22 22:20:22 -0700147 if err := d.unmarshalFields(m); !nerr.Merge(err) {
148 return err
149 }
150
151 return nerr.E
152}
153
154// unmarshalFields unmarshals the fields into the given protoreflect.Message.
155func (d decoder) unmarshalFields(m pref.Message) error {
156 var nerr errors.NonFatal
157 var reqNums set.Ints
158 var seenNums set.Ints
159
160 msgType := m.Type()
161 knownFields := m.KnownFields()
162 fieldDescs := msgType.Fields()
163 xtTypes := knownFields.ExtensionTypes()
164
Herbie Ongc96a79d2019-03-08 10:49:17 -0800165Loop:
166 for {
167 // Read field name.
168 jval, err := d.Read()
169 if !nerr.Merge(err) {
170 return err
171 }
172 switch jval.Type() {
173 default:
174 return unexpectedJSONError{jval}
175 case json.EndObject:
176 break Loop
177 case json.Name:
178 // Continue below.
179 }
180
181 name, err := jval.Name()
182 if !nerr.Merge(err) {
183 return err
184 }
185
Herbie Onge52379a2019-03-15 18:00:19 -0700186 // Get the FieldDescriptor.
187 var fd pref.FieldDescriptor
188 if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") {
189 // Only extension names are in [name] format.
190 xtName := pref.FullName(name[1 : len(name)-1])
191 xt := xtTypes.ByName(xtName)
192 if xt == nil {
193 xt, err = d.findExtension(xtName)
194 if err != nil && err != protoregistry.NotFound {
195 return errors.New("unable to resolve [%v]: %v", xtName, err)
196 }
197 if xt != nil {
198 xtTypes.Register(xt)
199 }
200 }
201 fd = xt
202 } else {
203 // The name can either be the JSON name or the proto field name.
204 fd = fieldDescs.ByJSONName(name)
205 if fd == nil {
206 fd = fieldDescs.ByName(pref.Name(name))
207 }
Herbie Ongc96a79d2019-03-08 10:49:17 -0800208 }
209
210 if fd == nil {
211 // Field is unknown.
212 // TODO: Provide option to ignore unknown message fields.
213 return newError("%v contains unknown field %s", msgType.FullName(), jval)
214 }
215
216 // Do not allow duplicate fields.
217 num := uint64(fd.Number())
218 if seenNums.Has(num) {
219 return newError("%v contains repeated field %s", msgType.FullName(), jval)
220 }
221 seenNums.Set(num)
222
Herbie Onge63c4c42019-03-22 22:20:22 -0700223 // No need to set values for JSON null unless the field type is
224 // google.protobuf.Value.
225 if d.Peek() == json.Null && !isKnownValue(fd) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800226 d.Read()
227 continue
228 }
229
230 if cardinality := fd.Cardinality(); cardinality == pref.Repeated {
231 // Map or list fields have cardinality of repeated.
Herbie Onge63c4c42019-03-22 22:20:22 -0700232 if err := d.unmarshalRepeated(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800233 return errors.New("%v|%q: %v", fd.FullName(), name, err)
234 }
235 } else {
236 // Required or optional fields.
Herbie Onge63c4c42019-03-22 22:20:22 -0700237 if err := d.unmarshalSingular(knownFields, fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800238 return errors.New("%v|%q: %v", fd.FullName(), name, err)
239 }
240 if cardinality == pref.Required {
241 reqNums.Set(num)
242 }
243 }
244 }
245
246 // Check for any missing required fields.
247 allReqNums := msgType.RequiredNumbers()
248 if reqNums.Len() != allReqNums.Len() {
249 for i := 0; i < allReqNums.Len(); i++ {
250 if num := allReqNums.Get(i); !reqNums.Has(uint64(num)) {
251 nerr.AppendRequiredNotSet(string(fieldDescs.ByNumber(num).FullName()))
252 }
253 }
254 }
255
256 return nerr.E
257}
258
Herbie Onge52379a2019-03-15 18:00:19 -0700259// findExtension returns protoreflect.ExtensionType from the resolver if found.
260func (d decoder) findExtension(xtName pref.FullName) (pref.ExtensionType, error) {
261 xt, err := d.resolver.FindExtensionByName(xtName)
262 if err == nil {
263 return xt, nil
264 }
265
266 // Check if this is a MessageSet extension field.
267 xt, err = d.resolver.FindExtensionByName(xtName + ".message_set_extension")
268 if err == nil && isMessageSetExtension(xt) {
269 return xt, nil
270 }
271 return nil, protoregistry.NotFound
272}
273
Herbie Ongc96a79d2019-03-08 10:49:17 -0800274// unmarshalSingular unmarshals to the non-repeated field specified by the given
275// FieldDescriptor.
Herbie Onge63c4c42019-03-22 22:20:22 -0700276func (d decoder) unmarshalSingular(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800277 var val pref.Value
278 var err error
279 num := fd.Number()
280
281 switch fd.Kind() {
282 case pref.MessageKind, pref.GroupKind:
283 m := knownFields.NewMessage(num)
284 err = d.unmarshalMessage(m)
285 val = pref.ValueOf(m)
286 default:
287 val, err = d.unmarshalScalar(fd)
288 }
289
290 var nerr errors.NonFatal
291 if !nerr.Merge(err) {
292 return err
293 }
294 knownFields.Set(num, val)
295 return nerr.E
296}
297
298// unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by
299// the given FieldDescriptor.
300func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) {
301 const b32 int = 32
302 const b64 int = 64
303
304 var nerr errors.NonFatal
305 jval, err := d.Read()
306 if !nerr.Merge(err) {
307 return pref.Value{}, err
308 }
309
310 kind := fd.Kind()
311 switch kind {
312 case pref.BoolKind:
313 return unmarshalBool(jval)
314
315 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
316 return unmarshalInt(jval, b32)
317
318 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
319 return unmarshalInt(jval, b64)
320
321 case pref.Uint32Kind, pref.Fixed32Kind:
322 return unmarshalUint(jval, b32)
323
324 case pref.Uint64Kind, pref.Fixed64Kind:
325 return unmarshalUint(jval, b64)
326
327 case pref.FloatKind:
328 return unmarshalFloat(jval, b32)
329
330 case pref.DoubleKind:
331 return unmarshalFloat(jval, b64)
332
333 case pref.StringKind:
334 pval, err := unmarshalString(jval)
335 if !nerr.Merge(err) {
336 return pval, err
337 }
338 return pval, nerr.E
339
340 case pref.BytesKind:
341 return unmarshalBytes(jval)
342
343 case pref.EnumKind:
344 return unmarshalEnum(jval, fd)
345 }
346
347 panic(fmt.Sprintf("invalid scalar kind %v", kind))
348}
349
350func unmarshalBool(jval json.Value) (pref.Value, error) {
351 if jval.Type() != json.Bool {
352 return pref.Value{}, unexpectedJSONError{jval}
353 }
354 b, err := jval.Bool()
355 return pref.ValueOf(b), err
356}
357
358func unmarshalInt(jval json.Value, bitSize int) (pref.Value, error) {
359 switch jval.Type() {
360 case json.Number:
361 return getInt(jval, bitSize)
362
363 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700364 // Decode number from string.
365 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800366 var nerr errors.NonFatal
367 jval, err := dec.Read()
368 if !nerr.Merge(err) {
369 return pref.Value{}, err
370 }
371 return getInt(jval, bitSize)
372 }
373 return pref.Value{}, unexpectedJSONError{jval}
374}
375
376func getInt(jval json.Value, bitSize int) (pref.Value, error) {
377 n, err := jval.Int(bitSize)
378 if err != nil {
379 return pref.Value{}, err
380 }
381 if bitSize == 32 {
382 return pref.ValueOf(int32(n)), nil
383 }
384 return pref.ValueOf(n), nil
385}
386
387func unmarshalUint(jval json.Value, bitSize int) (pref.Value, error) {
388 switch jval.Type() {
389 case json.Number:
390 return getUint(jval, bitSize)
391
392 case json.String:
Herbie Onge52379a2019-03-15 18:00:19 -0700393 // Decode number from string.
394 dec := json.NewDecoder([]byte(jval.String()))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800395 var nerr errors.NonFatal
396 jval, err := dec.Read()
397 if !nerr.Merge(err) {
398 return pref.Value{}, err
399 }
400 return getUint(jval, bitSize)
401 }
402 return pref.Value{}, unexpectedJSONError{jval}
403}
404
405func getUint(jval json.Value, bitSize int) (pref.Value, error) {
406 n, err := jval.Uint(bitSize)
407 if err != nil {
408 return pref.Value{}, err
409 }
410 if bitSize == 32 {
411 return pref.ValueOf(uint32(n)), nil
412 }
413 return pref.ValueOf(n), nil
414}
415
416func unmarshalFloat(jval json.Value, bitSize int) (pref.Value, error) {
417 switch jval.Type() {
418 case json.Number:
419 return getFloat(jval, bitSize)
420
421 case json.String:
422 s := jval.String()
423 switch s {
424 case "NaN":
425 if bitSize == 32 {
426 return pref.ValueOf(float32(math.NaN())), nil
427 }
428 return pref.ValueOf(math.NaN()), nil
429 case "Infinity":
430 if bitSize == 32 {
431 return pref.ValueOf(float32(math.Inf(+1))), nil
432 }
433 return pref.ValueOf(math.Inf(+1)), nil
434 case "-Infinity":
435 if bitSize == 32 {
436 return pref.ValueOf(float32(math.Inf(-1))), nil
437 }
438 return pref.ValueOf(math.Inf(-1)), nil
439 }
Herbie Onge52379a2019-03-15 18:00:19 -0700440 // Decode number from string.
441 dec := json.NewDecoder([]byte(s))
Herbie Ongc96a79d2019-03-08 10:49:17 -0800442 var nerr errors.NonFatal
443 jval, err := dec.Read()
444 if !nerr.Merge(err) {
445 return pref.Value{}, err
446 }
447 return getFloat(jval, bitSize)
448 }
449 return pref.Value{}, unexpectedJSONError{jval}
450}
451
452func getFloat(jval json.Value, bitSize int) (pref.Value, error) {
453 n, err := jval.Float(bitSize)
454 if err != nil {
455 return pref.Value{}, err
456 }
457 if bitSize == 32 {
458 return pref.ValueOf(float32(n)), nil
459 }
460 return pref.ValueOf(n), nil
461}
462
463func unmarshalString(jval json.Value) (pref.Value, error) {
464 if jval.Type() != json.String {
465 return pref.Value{}, unexpectedJSONError{jval}
466 }
467 return pref.ValueOf(jval.String()), nil
468}
469
470func unmarshalBytes(jval json.Value) (pref.Value, error) {
471 if jval.Type() != json.String {
472 return pref.Value{}, unexpectedJSONError{jval}
473 }
474
475 s := jval.String()
476 enc := base64.StdEncoding
477 if strings.ContainsAny(s, "-_") {
478 enc = base64.URLEncoding
479 }
480 if len(s)%4 != 0 {
481 enc = enc.WithPadding(base64.NoPadding)
482 }
483 b, err := enc.DecodeString(s)
484 if err != nil {
485 return pref.Value{}, err
486 }
487 return pref.ValueOf(b), nil
488}
489
490func unmarshalEnum(jval json.Value, fd pref.FieldDescriptor) (pref.Value, error) {
491 switch jval.Type() {
492 case json.String:
493 // Lookup EnumNumber based on name.
494 s := jval.String()
495 if enumVal := fd.EnumType().Values().ByName(pref.Name(s)); enumVal != nil {
496 return pref.ValueOf(enumVal.Number()), nil
497 }
498 return pref.Value{}, newError("invalid enum value %q", jval)
499
500 case json.Number:
501 n, err := jval.Int(32)
502 if err != nil {
503 return pref.Value{}, err
504 }
505 return pref.ValueOf(pref.EnumNumber(n)), nil
506 }
507
508 return pref.Value{}, unexpectedJSONError{jval}
509}
510
511// unmarshalRepeated unmarshals into a repeated field.
Herbie Onge63c4c42019-03-22 22:20:22 -0700512func (d decoder) unmarshalRepeated(knownFields pref.KnownFields, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800513 var nerr errors.NonFatal
514 num := fd.Number()
515 val := knownFields.Get(num)
516 if !fd.IsMap() {
Herbie Onge63c4c42019-03-22 22:20:22 -0700517 if err := d.unmarshalList(val.List(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800518 return err
519 }
520 } else {
Herbie Onge63c4c42019-03-22 22:20:22 -0700521 if err := d.unmarshalMap(val.Map(), fd); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800522 return err
523 }
524 }
525 return nerr.E
526}
527
528// unmarshalList unmarshals into given protoreflect.List.
Herbie Onge63c4c42019-03-22 22:20:22 -0700529func (d decoder) unmarshalList(list pref.List, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800530 var nerr errors.NonFatal
531 jval, err := d.Read()
532 if !nerr.Merge(err) {
533 return err
534 }
535 if jval.Type() != json.StartArray {
536 return unexpectedJSONError{jval}
537 }
538
539 switch fd.Kind() {
540 case pref.MessageKind, pref.GroupKind:
541 for {
542 m := list.NewMessage()
543 err := d.unmarshalMessage(m)
544 if !nerr.Merge(err) {
545 if e, ok := err.(unexpectedJSONError); ok {
546 if e.value.Type() == json.EndArray {
547 // Done with list.
548 return nerr.E
549 }
550 }
551 return err
552 }
553 list.Append(pref.ValueOf(m))
554 }
555 default:
556 for {
557 val, err := d.unmarshalScalar(fd)
558 if !nerr.Merge(err) {
559 if e, ok := err.(unexpectedJSONError); ok {
560 if e.value.Type() == json.EndArray {
561 // Done with list.
562 return nerr.E
563 }
564 }
565 return err
566 }
567 list.Append(val)
568 }
569 }
570 return nerr.E
571}
572
573// unmarshalMap unmarshals into given protoreflect.Map.
Herbie Onge63c4c42019-03-22 22:20:22 -0700574func (d decoder) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800575 var nerr errors.NonFatal
576
577 jval, err := d.Read()
578 if !nerr.Merge(err) {
579 return err
580 }
581 if jval.Type() != json.StartObject {
582 return unexpectedJSONError{jval}
583 }
584
585 fields := fd.MessageType().Fields()
586 keyDesc := fields.ByNumber(1)
587 valDesc := fields.ByNumber(2)
588
589 // Determine ahead whether map entry is a scalar type or a message type in
590 // order to call the appropriate unmarshalMapValue func inside the for loop
591 // below.
592 unmarshalMapValue := func() (pref.Value, error) {
593 return d.unmarshalScalar(valDesc)
594 }
595 switch valDesc.Kind() {
596 case pref.MessageKind, pref.GroupKind:
597 unmarshalMapValue = func() (pref.Value, error) {
Herbie Onge63c4c42019-03-22 22:20:22 -0700598 var nerr errors.NonFatal
Herbie Ongc96a79d2019-03-08 10:49:17 -0800599 m := mmap.NewMessage()
Herbie Onge63c4c42019-03-22 22:20:22 -0700600 if err := d.unmarshalMessage(m); !nerr.Merge(err) {
Herbie Ongc96a79d2019-03-08 10:49:17 -0800601 return pref.Value{}, err
602 }
Herbie Onge63c4c42019-03-22 22:20:22 -0700603 return pref.ValueOf(m), nerr.E
Herbie Ongc96a79d2019-03-08 10:49:17 -0800604 }
605 }
606
607Loop:
608 for {
609 // Read field name.
610 jval, err := d.Read()
611 if !nerr.Merge(err) {
612 return err
613 }
614 switch jval.Type() {
615 default:
616 return unexpectedJSONError{jval}
617 case json.EndObject:
618 break Loop
619 case json.Name:
620 // Continue.
621 }
622
623 name, err := jval.Name()
624 if !nerr.Merge(err) {
625 return err
626 }
627
628 // Unmarshal field name.
629 pkey, err := unmarshalMapKey(name, keyDesc)
630 if !nerr.Merge(err) {
631 return err
632 }
633
634 // Check for duplicate field name.
635 if mmap.Has(pkey) {
636 return newError("duplicate map key %q", jval)
637 }
638
639 // Read and unmarshal field value.
640 pval, err := unmarshalMapValue()
641 if !nerr.Merge(err) {
642 return err
643 }
644
645 mmap.Set(pkey, pval)
646 }
647
648 return nerr.E
649}
650
651// unmarshalMapKey converts given string into a protoreflect.MapKey. A map key type is any
652// integral or string type.
653func unmarshalMapKey(name string, fd pref.FieldDescriptor) (pref.MapKey, error) {
654 const b32 = 32
655 const b64 = 64
656 const base10 = 10
657
658 kind := fd.Kind()
659 switch kind {
660 case pref.StringKind:
661 return pref.ValueOf(name).MapKey(), nil
662
663 case pref.BoolKind:
664 switch name {
665 case "true":
666 return pref.ValueOf(true).MapKey(), nil
667 case "false":
668 return pref.ValueOf(false).MapKey(), nil
669 }
670 return pref.MapKey{}, errors.New("invalid value for boolean key %q", name)
671
672 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind:
673 n, err := strconv.ParseInt(name, base10, b32)
674 if err != nil {
675 return pref.MapKey{}, err
676 }
677 return pref.ValueOf(int32(n)).MapKey(), nil
678
679 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
680 n, err := strconv.ParseInt(name, base10, b64)
681 if err != nil {
682 return pref.MapKey{}, err
683 }
684 return pref.ValueOf(int64(n)).MapKey(), nil
685
686 case pref.Uint32Kind, pref.Fixed32Kind:
687 n, err := strconv.ParseUint(name, base10, b32)
688 if err != nil {
689 return pref.MapKey{}, err
690 }
691 return pref.ValueOf(uint32(n)).MapKey(), nil
692
693 case pref.Uint64Kind, pref.Fixed64Kind:
694 n, err := strconv.ParseUint(name, base10, b64)
695 if err != nil {
696 return pref.MapKey{}, err
697 }
698 return pref.ValueOf(uint64(n)).MapKey(), nil
699 }
700
701 panic(fmt.Sprintf("%s: invalid kind %s for map key", fd.FullName(), kind))
702}