...

Source file src/google.golang.org/protobuf/encoding/protojson/decode.go

Documentation: google.golang.org/protobuf/encoding/protojson

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

View as plain text