github.com/jhump/protocompile@v0.0.0-20221021153901-4f6f732835e8/options/options.go (about)

     1  // Package options contains the logic for interpreting options. The parse step
     2  // of compilation stores the options in uninterpreted form, which contains raw
     3  // identifiers and literal values.
     4  //
     5  // The process of interpreting an option is to resolve identifiers, by examining
     6  // descriptors for the Options types and their available extensions (custom
     7  // options). As field names are resolved, the values can be type-checked against
     8  // the types indicated in field descriptors.
     9  //
    10  // On success, the various fields and extensions of the options message are
    11  // populated and the field holding the uninterpreted form is cleared.
    12  package options
    13  
    14  import (
    15  	"bytes"
    16  	"fmt"
    17  	"math"
    18  	"sort"
    19  	"strings"
    20  
    21  	"google.golang.org/protobuf/proto"
    22  	"google.golang.org/protobuf/reflect/protoreflect"
    23  	"google.golang.org/protobuf/types/descriptorpb"
    24  	"google.golang.org/protobuf/types/dynamicpb"
    25  
    26  	"github.com/jhump/protocompile/ast"
    27  	"github.com/jhump/protocompile/internal"
    28  	"github.com/jhump/protocompile/linker"
    29  	"github.com/jhump/protocompile/parser"
    30  	"github.com/jhump/protocompile/reporter"
    31  )
    32  
    33  // Index is a mapping of AST nodes that define options to a corresponding path
    34  // into the containing file descriptor. The path is a sequence of field tags
    35  // and indexes that define a traversal path from the root (the file descriptor)
    36  // to the resolved option field.
    37  type Index map[*ast.OptionNode][]int32
    38  
    39  type interpreter struct {
    40  	file     file
    41  	resolver linker.Resolver
    42  	lenient  bool
    43  	reporter *reporter.Handler
    44  	index    Index
    45  }
    46  
    47  type file interface {
    48  	parser.Result
    49  	ResolveEnumType(protoreflect.FullName) protoreflect.EnumDescriptor
    50  	ResolveMessageType(protoreflect.FullName) protoreflect.MessageDescriptor
    51  	ResolveExtension(protoreflect.FullName) protoreflect.ExtensionTypeDescriptor
    52  }
    53  
    54  type noResolveFile struct {
    55  	parser.Result
    56  }
    57  
    58  func (n noResolveFile) ResolveEnumType(name protoreflect.FullName) protoreflect.EnumDescriptor {
    59  	return nil
    60  }
    61  
    62  func (n noResolveFile) ResolveMessageType(name protoreflect.FullName) protoreflect.MessageDescriptor {
    63  	return nil
    64  }
    65  
    66  func (n noResolveFile) ResolveExtension(name protoreflect.FullName) protoreflect.ExtensionTypeDescriptor {
    67  	return nil
    68  }
    69  
    70  // InterpretOptions interprets options in the given linked result, returning
    71  // an index that can be used to generate source code info. This step mutates
    72  // the linked result's underlying proto to move option elements out of the
    73  // "uninterpreted_option" fields and into proper option fields and extensions.
    74  //
    75  // The given handler is used to report errors and warnings. If any errors are
    76  // reported, this function returns a non-nil error.
    77  func InterpretOptions(linked linker.Result, handler *reporter.Handler) (Index, error) {
    78  	return interpretOptions(false, linked, handler)
    79  }
    80  
    81  // InterpretOptionsLenient interprets options in a lenient/best-effort way in
    82  // the given linked result, returning an index that can be used to generate
    83  // source code info. This step mutates the linked result's underlying proto to
    84  // move option elements out of the "uninterpreted_option" fields and into proper
    85  // option fields and extensions.
    86  //
    87  // In lenient more, errors resolving option names and type errors are ignored.
    88  // Any options that are uninterpretable (due to such errors) will remain in the
    89  // "uninterpreted_option" fields.
    90  func InterpretOptionsLenient(linked linker.Result) (Index, error) {
    91  	return interpretOptions(true, linked, reporter.NewHandler(nil))
    92  }
    93  
    94  // InterpretUnlinkedOptions does a best-effort attempt to interpret options in
    95  // the given parsed result, returning an index that can be used to generate
    96  // source code info. This step mutates the parsed result's underlying proto to
    97  // move option elements out of the "uninterpreted_option" fields and into proper
    98  // option fields and extensions.
    99  //
   100  // This is the same as InterpretOptionsLenient except that it accepts an
   101  // unlinked result. Because the file is unlinked, custom options cannot be
   102  // interpreted. Other errors resolving option names or type errors will be
   103  // effectively ignored. Any options that are uninterpretable (due to such
   104  // errors) will remain in the "uninterpreted_option" fields.
   105  func InterpretUnlinkedOptions(parsed parser.Result) (Index, error) {
   106  	return interpretOptions(true, noResolveFile{parsed}, reporter.NewHandler(nil))
   107  }
   108  
   109  func interpretOptions(lenient bool, file file, handler *reporter.Handler) (Index, error) {
   110  	interp := interpreter{
   111  		file:     file,
   112  		lenient:  lenient,
   113  		reporter: handler,
   114  		index:    Index{},
   115  	}
   116  	if f, ok := file.(linker.File); ok {
   117  		interp.resolver = linker.ResolverFromFile(f)
   118  	}
   119  
   120  	fd := file.Proto()
   121  	prefix := fd.GetPackage()
   122  	if prefix != "" {
   123  		prefix += "."
   124  	}
   125  	opts := fd.GetOptions()
   126  	if opts != nil {
   127  		if len(opts.UninterpretedOption) > 0 {
   128  			if remain, err := interp.interpretOptions(fd.GetName(), fd, opts, opts.UninterpretedOption); err != nil {
   129  				return nil, err
   130  			} else {
   131  				opts.UninterpretedOption = remain
   132  			}
   133  		}
   134  	}
   135  	for _, md := range fd.GetMessageType() {
   136  		fqn := prefix + md.GetName()
   137  		if err := interp.interpretMessageOptions(fqn, md); err != nil {
   138  			return nil, err
   139  		}
   140  	}
   141  	for _, fld := range fd.GetExtension() {
   142  		fqn := prefix + fld.GetName()
   143  		if err := interp.interpretFieldOptions(fqn, fld); err != nil {
   144  			return nil, err
   145  		}
   146  	}
   147  	for _, ed := range fd.GetEnumType() {
   148  		fqn := prefix + ed.GetName()
   149  		if err := interp.interpretEnumOptions(fqn, ed); err != nil {
   150  			return nil, err
   151  		}
   152  	}
   153  	for _, sd := range fd.GetService() {
   154  		fqn := prefix + sd.GetName()
   155  		opts := sd.GetOptions()
   156  		if len(opts.GetUninterpretedOption()) > 0 {
   157  			if remain, err := interp.interpretOptions(fqn, sd, opts, opts.UninterpretedOption); err != nil {
   158  				return nil, err
   159  			} else {
   160  				opts.UninterpretedOption = remain
   161  			}
   162  		}
   163  		for _, mtd := range sd.GetMethod() {
   164  			mtdFqn := fqn + "." + mtd.GetName()
   165  			opts := mtd.GetOptions()
   166  			if len(opts.GetUninterpretedOption()) > 0 {
   167  				if remain, err := interp.interpretOptions(mtdFqn, mtd, opts, opts.UninterpretedOption); err != nil {
   168  					return nil, err
   169  				} else {
   170  					opts.UninterpretedOption = remain
   171  				}
   172  			}
   173  		}
   174  	}
   175  	return interp.index, nil
   176  }
   177  
   178  func (interp *interpreter) nodeInfo(n ast.Node) ast.NodeInfo {
   179  	return interp.file.FileNode().NodeInfo(n)
   180  }
   181  
   182  func (interp *interpreter) interpretMessageOptions(fqn string, md *descriptorpb.DescriptorProto) error {
   183  	opts := md.GetOptions()
   184  	if opts != nil {
   185  		if len(opts.UninterpretedOption) > 0 {
   186  			if remain, err := interp.interpretOptions(fqn, md, opts, opts.UninterpretedOption); err != nil {
   187  				return err
   188  			} else {
   189  				opts.UninterpretedOption = remain
   190  			}
   191  		}
   192  	}
   193  	for _, fld := range md.GetField() {
   194  		fldFqn := fqn + "." + fld.GetName()
   195  		if err := interp.interpretFieldOptions(fldFqn, fld); err != nil {
   196  			return err
   197  		}
   198  	}
   199  	for _, ood := range md.GetOneofDecl() {
   200  		oodFqn := fqn + "." + ood.GetName()
   201  		opts := ood.GetOptions()
   202  		if len(opts.GetUninterpretedOption()) > 0 {
   203  			if remain, err := interp.interpretOptions(oodFqn, ood, opts, opts.UninterpretedOption); err != nil {
   204  				return err
   205  			} else {
   206  				opts.UninterpretedOption = remain
   207  			}
   208  		}
   209  	}
   210  	for _, fld := range md.GetExtension() {
   211  		fldFqn := fqn + "." + fld.GetName()
   212  		if err := interp.interpretFieldOptions(fldFqn, fld); err != nil {
   213  			return err
   214  		}
   215  	}
   216  	for _, er := range md.GetExtensionRange() {
   217  		erFqn := fmt.Sprintf("%s.%d-%d", fqn, er.GetStart(), er.GetEnd())
   218  		opts := er.GetOptions()
   219  		if len(opts.GetUninterpretedOption()) > 0 {
   220  			if remain, err := interp.interpretOptions(erFqn, er, opts, opts.UninterpretedOption); err != nil {
   221  				return err
   222  			} else {
   223  				opts.UninterpretedOption = remain
   224  			}
   225  		}
   226  	}
   227  	for _, nmd := range md.GetNestedType() {
   228  		nmdFqn := fqn + "." + nmd.GetName()
   229  		if err := interp.interpretMessageOptions(nmdFqn, nmd); err != nil {
   230  			return err
   231  		}
   232  	}
   233  	for _, ed := range md.GetEnumType() {
   234  		edFqn := fqn + "." + ed.GetName()
   235  		if err := interp.interpretEnumOptions(edFqn, ed); err != nil {
   236  			return err
   237  		}
   238  	}
   239  	return nil
   240  }
   241  
   242  func (interp *interpreter) interpretFieldOptions(fqn string, fld *descriptorpb.FieldDescriptorProto) error {
   243  	opts := fld.GetOptions()
   244  	if len(opts.GetUninterpretedOption()) > 0 {
   245  		uo := opts.UninterpretedOption
   246  		scope := fmt.Sprintf("field %s", fqn)
   247  
   248  		// process json_name pseudo-option
   249  		if index, err := internal.FindOption(interp.file, interp.reporter, scope, uo, "json_name"); err != nil && !interp.lenient {
   250  			return err
   251  		} else if index >= 0 {
   252  			opt := uo[index]
   253  			optNode := interp.file.OptionNode(opt)
   254  
   255  			// attribute source code info
   256  			if on, ok := optNode.(*ast.OptionNode); ok {
   257  				interp.index[on] = []int32{-1, internal.Field_jsonNameTag}
   258  			}
   259  			uo = internal.RemoveOption(uo, index)
   260  			if opt.StringValue == nil {
   261  				if err := interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetValue()).Start(), "%s: expecting string value for json_name option", scope); err != nil {
   262  					return err
   263  				}
   264  			} else {
   265  				fld.JsonName = proto.String(string(opt.StringValue))
   266  			}
   267  		}
   268  
   269  		// and process default pseudo-option
   270  		if index, err := interp.processDefaultOption(scope, fqn, fld, uo); err != nil && !interp.lenient {
   271  			return err
   272  		} else if index >= 0 {
   273  			// attribute source code info
   274  			optNode := interp.file.OptionNode(uo[index])
   275  			if on, ok := optNode.(*ast.OptionNode); ok {
   276  				interp.index[on] = []int32{-1, internal.Field_defaultTag}
   277  			}
   278  			uo = internal.RemoveOption(uo, index)
   279  		}
   280  
   281  		if len(uo) == 0 {
   282  			// no real options, only pseudo-options above? clear out options
   283  			fld.Options = nil
   284  		} else if remain, err := interp.interpretOptions(fqn, fld, opts, uo); err != nil {
   285  			return err
   286  		} else {
   287  			opts.UninterpretedOption = remain
   288  		}
   289  	}
   290  	return nil
   291  }
   292  
   293  func (interp *interpreter) processDefaultOption(scope string, fqn string, fld *descriptorpb.FieldDescriptorProto, uos []*descriptorpb.UninterpretedOption) (defaultIndex int, err error) {
   294  	found, err := internal.FindOption(interp.file, interp.reporter, scope, uos, "default")
   295  	if err != nil || found == -1 {
   296  		return -1, err
   297  	}
   298  	opt := uos[found]
   299  	optNode := interp.file.OptionNode(opt)
   300  	if fld.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
   301  		return -1, interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetName()).Start(), "%s: default value cannot be set because field is repeated", scope)
   302  	}
   303  	if fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP || fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_MESSAGE {
   304  		return -1, interp.reporter.HandleErrorf(interp.nodeInfo(optNode.GetName()).Start(), "%s: default value cannot be set because field is a message", scope)
   305  	}
   306  	val := optNode.GetValue()
   307  	if _, ok := val.(*ast.MessageLiteralNode); ok {
   308  		return -1, interp.reporter.HandleErrorf(interp.nodeInfo(val).Start(), "%s: default value cannot be a message", scope)
   309  	}
   310  	mc := &messageContext{
   311  		res:         interp.file,
   312  		file:        interp.file.Proto(),
   313  		elementName: fqn,
   314  		elementType: descriptorType(fld),
   315  		option:      opt,
   316  	}
   317  	var v interface{}
   318  	if fld.GetType() == descriptorpb.FieldDescriptorProto_TYPE_ENUM {
   319  		ed := interp.file.ResolveEnumType(protoreflect.FullName(fld.GetTypeName()))
   320  		ev, err := interp.enumFieldValue(mc, ed, val)
   321  		if err != nil {
   322  			return -1, interp.reporter.HandleError(err)
   323  		}
   324  		v = string(ev.Name())
   325  	} else {
   326  		v, err = interp.scalarFieldValue(mc, fld.GetType(), val)
   327  		if err != nil {
   328  			return -1, interp.reporter.HandleError(err)
   329  		}
   330  	}
   331  	if str, ok := v.(string); ok {
   332  		fld.DefaultValue = proto.String(str)
   333  	} else if b, ok := v.([]byte); ok {
   334  		fld.DefaultValue = proto.String(encodeDefaultBytes(b))
   335  	} else {
   336  		var flt float64
   337  		var ok bool
   338  		if flt, ok = v.(float64); !ok {
   339  			var flt32 float32
   340  			if flt32, ok = v.(float32); ok {
   341  				flt = float64(flt32)
   342  			}
   343  		}
   344  		if ok {
   345  			if math.IsInf(flt, 1) {
   346  				fld.DefaultValue = proto.String("inf")
   347  			} else if ok && math.IsInf(flt, -1) {
   348  				fld.DefaultValue = proto.String("-inf")
   349  			} else if ok && math.IsNaN(flt) {
   350  				fld.DefaultValue = proto.String("nan")
   351  			} else {
   352  				fld.DefaultValue = proto.String(fmt.Sprintf("%v", v))
   353  			}
   354  		} else {
   355  			fld.DefaultValue = proto.String(fmt.Sprintf("%v", v))
   356  		}
   357  	}
   358  	return found, nil
   359  }
   360  
   361  func encodeDefaultBytes(b []byte) string {
   362  	var buf bytes.Buffer
   363  	internal.WriteEscapedBytes(&buf, b)
   364  	return buf.String()
   365  }
   366  
   367  func (interp *interpreter) interpretEnumOptions(fqn string, ed *descriptorpb.EnumDescriptorProto) error {
   368  	opts := ed.GetOptions()
   369  	if opts != nil {
   370  		if len(opts.UninterpretedOption) > 0 {
   371  			if remain, err := interp.interpretOptions(fqn, ed, opts, opts.UninterpretedOption); err != nil {
   372  				return err
   373  			} else {
   374  				opts.UninterpretedOption = remain
   375  			}
   376  		}
   377  	}
   378  	for _, evd := range ed.GetValue() {
   379  		evdFqn := fqn + "." + evd.GetName()
   380  		opts := evd.GetOptions()
   381  		if len(opts.GetUninterpretedOption()) > 0 {
   382  			if remain, err := interp.interpretOptions(evdFqn, evd, opts, opts.UninterpretedOption); err != nil {
   383  				return err
   384  			} else {
   385  				opts.UninterpretedOption = remain
   386  			}
   387  		}
   388  	}
   389  	return nil
   390  }
   391  
   392  func (interp *interpreter) interpretOptions(fqn string, element, opts proto.Message, uninterpreted []*descriptorpb.UninterpretedOption) ([]*descriptorpb.UninterpretedOption, error) {
   393  	optsFqn := string(opts.ProtoReflect().Descriptor().FullName())
   394  	var msg protoreflect.Message
   395  	// see if the parse included an override copy for these options
   396  	if md := interp.file.ResolveMessageType(protoreflect.FullName(optsFqn)); md != nil {
   397  		dm := newDynamic(md)
   398  		if err := cloneInto(dm, opts, nil); err != nil {
   399  			node := interp.file.Node(element)
   400  			return nil, interp.reporter.HandleError(reporter.Error(interp.nodeInfo(node).Start(), err))
   401  		}
   402  		msg = dm
   403  	} else {
   404  		msg = proto.Clone(opts).ProtoReflect()
   405  	}
   406  
   407  	mc := &messageContext{res: interp.file, file: interp.file.Proto(), elementName: fqn, elementType: descriptorType(element)}
   408  	var remain []*descriptorpb.UninterpretedOption
   409  	for _, uo := range uninterpreted {
   410  		node := interp.file.OptionNode(uo)
   411  		if !uo.Name[0].GetIsExtension() && uo.Name[0].GetNamePart() == "uninterpreted_option" {
   412  			if interp.lenient {
   413  				remain = append(remain, uo)
   414  				continue
   415  			}
   416  			// uninterpreted_option might be found reflectively, but is not actually valid for use
   417  			if err := interp.reporter.HandleErrorf(interp.nodeInfo(node.GetName()).Start(), "%vinvalid option 'uninterpreted_option'", mc); err != nil {
   418  				return nil, err
   419  			}
   420  		}
   421  		mc.option = uo
   422  		path, err := interp.interpretField(mc, element, msg, uo, 0, nil)
   423  		if err != nil {
   424  			if interp.lenient {
   425  				remain = append(remain, uo)
   426  				continue
   427  			}
   428  			return nil, err
   429  		}
   430  		if optn, ok := node.(*ast.OptionNode); ok {
   431  			interp.index[optn] = path
   432  		}
   433  	}
   434  
   435  	if interp.lenient {
   436  		// If we're lenient, then we don't want to clobber the passed in message
   437  		// and leave it partially populated. So we convert into a copy first
   438  		optsClone := opts.ProtoReflect().New().Interface()
   439  		if err := cloneInto(optsClone, msg.Interface(), interp.resolver); err != nil {
   440  			// TODO: do this in a more granular way, so we can convert individual
   441  			// fields and leave bad ones uninterpreted instead of skipping all of
   442  			// the work we've done so far.
   443  			return uninterpreted, nil
   444  		}
   445  		// conversion from dynamic message above worked, so now
   446  		// it is safe to overwrite the passed in message
   447  		proto.Reset(opts)
   448  		proto.Merge(opts, optsClone)
   449  
   450  		return remain, nil
   451  	}
   452  
   453  	if err := validateRecursive(msg, ""); err != nil {
   454  		node := interp.file.Node(element)
   455  		if err := interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(), "error in %s options: %v", descriptorType(element), err); err != nil {
   456  			return nil, err
   457  		}
   458  	}
   459  
   460  	// now try to convert into the passed in message and fail if not successful
   461  	if err := cloneInto(opts, msg.Interface(), interp.resolver); err != nil {
   462  		node := interp.file.Node(element)
   463  		return nil, interp.reporter.HandleError(reporter.Error(interp.nodeInfo(node).Start(), err))
   464  	}
   465  
   466  	return nil, nil
   467  }
   468  
   469  func cloneInto(dest proto.Message, src proto.Message, res linker.Resolver) error {
   470  	if dest.ProtoReflect().Descriptor() == src.ProtoReflect().Descriptor() {
   471  		proto.Reset(dest)
   472  		proto.Merge(dest, src)
   473  		if err := proto.CheckInitialized(dest); err != nil {
   474  			return err
   475  		}
   476  		return nil
   477  	}
   478  
   479  	// If descriptors are not the same, we could have field descriptors in src that
   480  	// don't match the ones in dest. There's no easy/sane way to handle that. So we
   481  	// just marshal to bytes and back to do this
   482  	data, err := proto.Marshal(src)
   483  	if err != nil {
   484  		return err
   485  	}
   486  	return proto.UnmarshalOptions{Resolver: res}.Unmarshal(data, dest)
   487  }
   488  
   489  func newDynamic(md protoreflect.MessageDescriptor) *deterministicDynamic {
   490  	return &deterministicDynamic{Message: dynamicpb.NewMessage(md)}
   491  }
   492  
   493  type deterministicDynamic struct {
   494  	*dynamicpb.Message
   495  }
   496  
   497  // ProtoReflect implements the protoreflect.ProtoMessage interface.
   498  func (d *deterministicDynamic) ProtoReflect() protoreflect.Message {
   499  	return d
   500  }
   501  
   502  func (d *deterministicDynamic) Interface() protoreflect.ProtoMessage {
   503  	return d
   504  }
   505  
   506  func (d *deterministicDynamic) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
   507  	var fields []protoreflect.FieldDescriptor
   508  	d.Message.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool {
   509  		fields = append(fields, fd)
   510  		return true
   511  	})
   512  	// simple sort for deterministic marshaling
   513  	sort.Slice(fields, func(i, j int) bool {
   514  		return fields[i].Number() < fields[j].Number()
   515  	})
   516  	for _, fld := range fields {
   517  		if !f(fld, d.Get(fld)) {
   518  			return
   519  		}
   520  	}
   521  }
   522  
   523  func (d *deterministicDynamic) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
   524  	v := d.Message.Get(fd)
   525  	if v.IsValid() && fd.IsMap() {
   526  		mp := v.Map()
   527  		if _, ok := mp.(*deterministicMap); !ok {
   528  			return protoreflect.ValueOfMap(&deterministicMap{Map: v.Map(), keyKind: fd.MapKey().Kind()})
   529  		}
   530  	}
   531  	return v
   532  }
   533  
   534  type deterministicMap struct {
   535  	protoreflect.Map
   536  	keyKind protoreflect.Kind
   537  }
   538  
   539  func (m *deterministicMap) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
   540  	var keys []protoreflect.MapKey
   541  	m.Map.Range(func(k protoreflect.MapKey, _ protoreflect.Value) bool {
   542  		keys = append(keys, k)
   543  		return true
   544  	})
   545  	sort.Slice(keys, func(i, j int) bool {
   546  		switch m.keyKind {
   547  		case protoreflect.BoolKind:
   548  			return !keys[i].Bool() && keys[j].Bool()
   549  		case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind,
   550  			protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
   551  			return keys[i].Int() < keys[j].Int()
   552  		case protoreflect.Uint32Kind, protoreflect.Fixed32Kind,
   553  			protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
   554  			return keys[i].Uint() < keys[j].Uint()
   555  		case protoreflect.StringKind:
   556  			return keys[i].String() < keys[j].String()
   557  		default:
   558  			panic("invalid kind: " + m.keyKind.String())
   559  		}
   560  	})
   561  	for _, key := range keys {
   562  		if !f(key, m.Map.Get(key)) {
   563  			break
   564  		}
   565  	}
   566  }
   567  
   568  func validateRecursive(msg protoreflect.Message, prefix string) error {
   569  	flds := msg.Descriptor().Fields()
   570  	var missingFields []string
   571  	for i := 0; i < flds.Len(); i++ {
   572  		fld := flds.Get(i)
   573  		if fld.Cardinality() == protoreflect.Required && !msg.Has(fld) {
   574  			missingFields = append(missingFields, fmt.Sprintf("%s%s", prefix, fld.Name()))
   575  		}
   576  	}
   577  	if len(missingFields) > 0 {
   578  		return fmt.Errorf("some required fields missing: %v", strings.Join(missingFields, ", "))
   579  	}
   580  
   581  	var err error
   582  	msg.Range(func(fld protoreflect.FieldDescriptor, val protoreflect.Value) bool {
   583  		if fld.IsMap() {
   584  			md := fld.MapValue().Message()
   585  			if md != nil {
   586  				val.Map().Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
   587  					chprefix := fmt.Sprintf("%s%s[%v].", prefix, fieldName(fld), k)
   588  					err = validateRecursive(v.Message(), chprefix)
   589  					if err != nil {
   590  						return false
   591  					}
   592  					return true
   593  				})
   594  				if err != nil {
   595  					return false
   596  				}
   597  			}
   598  		} else {
   599  			md := fld.Message()
   600  			if md != nil {
   601  				if fld.IsList() {
   602  					sl := val.List()
   603  					for i := 0; i < sl.Len(); i++ {
   604  						v := sl.Get(i)
   605  						chprefix := fmt.Sprintf("%s%s[%d].", prefix, fieldName(fld), i)
   606  						err = validateRecursive(v.Message(), chprefix)
   607  						if err != nil {
   608  							return false
   609  						}
   610  					}
   611  				} else {
   612  					chprefix := fmt.Sprintf("%s%s.", prefix, fieldName(fld))
   613  					err = validateRecursive(val.Message(), chprefix)
   614  					if err != nil {
   615  						return false
   616  					}
   617  				}
   618  			}
   619  		}
   620  		return true
   621  	})
   622  	return err
   623  }
   624  
   625  func (interp *interpreter) interpretField(mc *messageContext, element proto.Message, msg protoreflect.Message, opt *descriptorpb.UninterpretedOption, nameIndex int, pathPrefix []int32) (path []int32, err error) {
   626  	var fld protoreflect.FieldDescriptor
   627  	nm := opt.GetName()[nameIndex]
   628  	node := interp.file.OptionNamePartNode(nm)
   629  	if nm.GetIsExtension() {
   630  		extName := nm.GetNamePart()
   631  		if extName[0] == '.' {
   632  			extName = extName[1:] /* skip leading dot */
   633  		}
   634  		fld = interp.file.ResolveExtension(protoreflect.FullName(extName))
   635  		if fld == nil {
   636  			return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(),
   637  				"%vunrecognized extension %s of %s",
   638  				mc, extName, msg.Descriptor().FullName())
   639  		}
   640  		if fld.ContainingMessage().FullName() != msg.Descriptor().FullName() {
   641  			return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(),
   642  				"%vextension %s should extend %s but instead extends %s",
   643  				mc, extName, msg.Descriptor().FullName(), fld.ContainingMessage().FullName())
   644  		}
   645  	} else {
   646  		fld = msg.Descriptor().Fields().ByName(protoreflect.Name(nm.GetNamePart()))
   647  		if fld == nil {
   648  			return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(),
   649  				"%vfield %s of %s does not exist",
   650  				mc, nm.GetNamePart(), msg.Descriptor().FullName())
   651  		}
   652  	}
   653  
   654  	path = append(pathPrefix, int32(fld.Number()))
   655  
   656  	if len(opt.GetName()) > nameIndex+1 {
   657  		nextnm := opt.GetName()[nameIndex+1]
   658  		nextnode := interp.file.OptionNamePartNode(nextnm)
   659  		k := fld.Kind()
   660  		if k != protoreflect.MessageKind && k != protoreflect.GroupKind {
   661  			return nil, interp.reporter.HandleErrorf(interp.nodeInfo(nextnode).Start(),
   662  				"%vcannot set field %s because %s is not a message",
   663  				mc, nextnm.GetNamePart(), nm.GetNamePart())
   664  		}
   665  		if fld.Cardinality() == protoreflect.Repeated {
   666  			return nil, interp.reporter.HandleErrorf(interp.nodeInfo(nextnode).Start(),
   667  				"%vcannot set field %s because %s is repeated (must use an aggregate)",
   668  				mc, nextnm.GetNamePart(), nm.GetNamePart())
   669  		}
   670  		var fdm protoreflect.Message
   671  		if msg.Has(fld) {
   672  			v := msg.Mutable(fld)
   673  			fdm = v.Message()
   674  		} else {
   675  			if ood := fld.ContainingOneof(); ood != nil {
   676  				existingFld := msg.WhichOneof(ood)
   677  				if existingFld != nil && existingFld.Number() != fld.Number() {
   678  					return nil, interp.reporter.HandleErrorf(interp.nodeInfo(node).Start(),
   679  						"%voneof %q already has field %q set",
   680  						mc, ood.Name(), fieldName(existingFld))
   681  				}
   682  			}
   683  			fdm = newDynamic(fld.Message())
   684  			msg.Set(fld, protoreflect.ValueOfMessage(fdm))
   685  		}
   686  		// recurse to set next part of name
   687  		return interp.interpretField(mc, element, fdm, opt, nameIndex+1, path)
   688  	}
   689  
   690  	optNode := interp.file.OptionNode(opt)
   691  	if err := interp.setOptionField(mc, msg, fld, node, optNode.GetValue()); err != nil {
   692  		return nil, interp.reporter.HandleError(err)
   693  	}
   694  	if fld.IsMap() {
   695  		path = append(path, int32(msg.Get(fld).Map().Len())-1)
   696  	} else if fld.IsList() {
   697  		path = append(path, int32(msg.Get(fld).List().Len())-1)
   698  	}
   699  	return path, nil
   700  }
   701  
   702  func (interp *interpreter) setOptionField(mc *messageContext, msg protoreflect.Message, fld protoreflect.FieldDescriptor, name ast.Node, val ast.ValueNode) error {
   703  	v := val.Value()
   704  	if sl, ok := v.([]ast.ValueNode); ok {
   705  		// handle slices a little differently than the others
   706  		if fld.Cardinality() != protoreflect.Repeated {
   707  			return reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue is an array but field is not repeated", mc)
   708  		}
   709  		origPath := mc.optAggPath
   710  		defer func() {
   711  			mc.optAggPath = origPath
   712  		}()
   713  		for index, item := range sl {
   714  			mc.optAggPath = fmt.Sprintf("%s[%d]", origPath, index)
   715  			value, err := interp.fieldValue(mc, fld, item)
   716  			if err != nil {
   717  				return err
   718  			}
   719  			if fld.IsMap() {
   720  				entry := value.Message()
   721  				key := entry.Get(fld.MapKey()).MapKey()
   722  				val := entry.Get(fld.MapValue())
   723  				if dm, ok := val.Interface().(*dynamicpb.Message); ok && (dm == nil || !dm.IsValid()) {
   724  					val = protoreflect.ValueOfMessage(newDynamic(fld.MapValue().Message()))
   725  				}
   726  				msg.Mutable(fld).Map().Set(key, val)
   727  			} else {
   728  				msg.Mutable(fld).List().Append(value)
   729  			}
   730  		}
   731  		return nil
   732  	}
   733  
   734  	value, err := interp.fieldValue(mc, fld, val)
   735  	if err != nil {
   736  		return err
   737  	}
   738  
   739  	if ood := fld.ContainingOneof(); ood != nil {
   740  		existingFld := msg.WhichOneof(ood)
   741  		if existingFld != nil && existingFld.Number() != fld.Number() {
   742  			return reporter.Errorf(interp.nodeInfo(name).Start(), "%voneof %q already has field %q set", mc, ood.Name(), fieldName(existingFld))
   743  		}
   744  	}
   745  
   746  	if fld.IsMap() {
   747  		entry := value.Message()
   748  		key := entry.Get(fld.MapKey()).MapKey()
   749  		val := entry.Get(fld.MapValue())
   750  		if dm, ok := val.Interface().(*dynamicpb.Message); ok && (dm == nil || !dm.IsValid()) {
   751  			val = protoreflect.ValueOfMessage(newDynamic(fld.MapValue().Message()))
   752  		}
   753  		msg.Mutable(fld).Map().Set(key, val)
   754  	} else if fld.IsList() {
   755  		msg.Mutable(fld).List().Append(value)
   756  	} else {
   757  		if msg.Has(fld) {
   758  			return reporter.Errorf(interp.nodeInfo(name).Start(), "%vnon-repeated option field %s already set", mc, fieldName(fld))
   759  		}
   760  		msg.Set(fld, value)
   761  	}
   762  
   763  	return nil
   764  }
   765  
   766  type messageContext struct {
   767  	res         parser.Result
   768  	file        *descriptorpb.FileDescriptorProto
   769  	elementType string
   770  	elementName string
   771  	option      *descriptorpb.UninterpretedOption
   772  	optAggPath  string
   773  }
   774  
   775  func (c *messageContext) String() string {
   776  	var ctx bytes.Buffer
   777  	if c.elementType != "file" {
   778  		_, _ = fmt.Fprintf(&ctx, "%s %s: ", c.elementType, c.elementName)
   779  	}
   780  	if c.option != nil && c.option.Name != nil {
   781  		ctx.WriteString("option ")
   782  		writeOptionName(&ctx, c.option.Name)
   783  		if c.res.AST() == nil {
   784  			// if we have no source position info, try to provide as much context
   785  			// as possible (if nodes != nil, we don't need this because any errors
   786  			// will actually have file and line numbers)
   787  			if c.optAggPath != "" {
   788  				_, _ = fmt.Fprintf(&ctx, " at %s", c.optAggPath)
   789  			}
   790  		}
   791  		ctx.WriteString(": ")
   792  	}
   793  	return ctx.String()
   794  }
   795  
   796  func writeOptionName(buf *bytes.Buffer, parts []*descriptorpb.UninterpretedOption_NamePart) {
   797  	first := true
   798  	for _, p := range parts {
   799  		if first {
   800  			first = false
   801  		} else {
   802  			buf.WriteByte('.')
   803  		}
   804  		nm := p.GetNamePart()
   805  		if nm[0] == '.' {
   806  			// skip leading dot
   807  			nm = nm[1:]
   808  		}
   809  		if p.GetIsExtension() {
   810  			buf.WriteByte('(')
   811  			buf.WriteString(nm)
   812  			buf.WriteByte(')')
   813  		} else {
   814  			buf.WriteString(nm)
   815  		}
   816  	}
   817  }
   818  
   819  func fieldName(fld protoreflect.FieldDescriptor) string {
   820  	if fld.IsExtension() {
   821  		return fmt.Sprintf("(%s)", fld.FullName())
   822  	} else {
   823  		return string(fld.Name())
   824  	}
   825  }
   826  
   827  func valueKind(val interface{}) string {
   828  	switch val := val.(type) {
   829  	case ast.Identifier:
   830  		return "identifier"
   831  	case bool:
   832  		return "bool"
   833  	case int64:
   834  		if val < 0 {
   835  			return "negative integer"
   836  		}
   837  		return "integer"
   838  	case uint64:
   839  		return "integer"
   840  	case float64:
   841  		return "double"
   842  	case string, []byte:
   843  		return "string"
   844  	case []*ast.MessageFieldNode:
   845  		return "message"
   846  	case []ast.ValueNode:
   847  		return "array"
   848  	default:
   849  		return fmt.Sprintf("%T", val)
   850  	}
   851  }
   852  
   853  func (interp *interpreter) fieldValue(mc *messageContext, fld protoreflect.FieldDescriptor, val ast.ValueNode) (protoreflect.Value, error) {
   854  	k := fld.Kind()
   855  	switch k {
   856  	case protoreflect.EnumKind:
   857  		evd, err := interp.enumFieldValue(mc, fld.Enum(), val)
   858  		if err != nil {
   859  			return protoreflect.Value{}, err
   860  		}
   861  		return protoreflect.ValueOfEnum(evd.Number()), nil
   862  
   863  	case protoreflect.MessageKind, protoreflect.GroupKind:
   864  		v := val.Value()
   865  		if aggs, ok := v.([]*ast.MessageFieldNode); ok {
   866  			fmd := fld.Message()
   867  			fdm := newDynamic(fmd)
   868  			origPath := mc.optAggPath
   869  			defer func() {
   870  				mc.optAggPath = origPath
   871  			}()
   872  			for _, a := range aggs {
   873  				if origPath == "" {
   874  					mc.optAggPath = a.Name.Value()
   875  				} else {
   876  					mc.optAggPath = origPath + "." + a.Name.Value()
   877  				}
   878  				var ffld protoreflect.FieldDescriptor
   879  				if a.Name.IsExtension() {
   880  					n := string(a.Name.Name.AsIdentifier())
   881  					ffld = interp.file.ResolveExtension(protoreflect.FullName(n))
   882  					if ffld == nil {
   883  						// may need to qualify with package name
   884  						pkg := mc.file.GetPackage()
   885  						if pkg != "" {
   886  							ffld = interp.file.ResolveExtension(protoreflect.FullName(pkg + "." + n))
   887  						}
   888  					}
   889  				} else {
   890  					ffld = fmd.Fields().ByName(protoreflect.Name(a.Name.Value()))
   891  					// Groups are indicated in the text format by the group name (which is
   892  					// camel-case), NOT the field name (which is lower-case).
   893  					// ...but only regular fields, not extensions that are groups...
   894  					if ffld != nil && ffld.Kind() == protoreflect.GroupKind && ffld.Message().Name() != protoreflect.Name(a.Name.Value()) {
   895  						// this is kind of silly to fail here, but this mimics protoc behavior
   896  						return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vfield %s not found (did you mean the group named %s?)", mc, a.Name.Value(), ffld.Message().Name())
   897  					}
   898  					if ffld == nil {
   899  						// could be a group name
   900  						for i := 0; i < fmd.Fields().Len(); i++ {
   901  							fd := fmd.Fields().Get(i)
   902  							if fd.Kind() == protoreflect.GroupKind && fd.Message().Name() == protoreflect.Name(a.Name.Value()) {
   903  								// found it!
   904  								ffld = fd
   905  								break
   906  							}
   907  						}
   908  					}
   909  				}
   910  				if ffld == nil {
   911  					return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vfield %s not found", mc, string(a.Name.Name.AsIdentifier()))
   912  				}
   913  				if err := interp.setOptionField(mc, fdm, ffld, a.Name, a.Val); err != nil {
   914  					return protoreflect.Value{}, err
   915  				}
   916  			}
   917  			return protoreflect.ValueOfMessage(fdm), nil
   918  		}
   919  		return protoreflect.Value{}, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting message, got %s", mc, valueKind(v))
   920  
   921  	default:
   922  		v, err := interp.scalarFieldValue(mc, descriptorpb.FieldDescriptorProto_Type(k), val)
   923  		if err != nil {
   924  			return protoreflect.Value{}, err
   925  		}
   926  		return protoreflect.ValueOf(v), nil
   927  	}
   928  }
   929  
   930  func (interp *interpreter) enumFieldValue(mc *messageContext, ed protoreflect.EnumDescriptor, val ast.ValueNode) (protoreflect.EnumValueDescriptor, error) {
   931  	v := val.Value()
   932  	if id, ok := v.(ast.Identifier); ok {
   933  		ev := ed.Values().ByName(protoreflect.Name(id))
   934  		if ev == nil {
   935  			return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%venum %s has no value named %s", mc, ed.FullName(), id)
   936  		}
   937  		return ev, nil
   938  	}
   939  	return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting enum, got %s", mc, valueKind(v))
   940  }
   941  
   942  func (interp *interpreter) scalarFieldValue(mc *messageContext, fldType descriptorpb.FieldDescriptorProto_Type, val ast.ValueNode) (interface{}, error) {
   943  	v := val.Value()
   944  	switch fldType {
   945  	case descriptorpb.FieldDescriptorProto_TYPE_BOOL:
   946  		if b, ok := v.(bool); ok {
   947  			return b, nil
   948  		}
   949  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting bool, got %s", mc, valueKind(v))
   950  	case descriptorpb.FieldDescriptorProto_TYPE_BYTES:
   951  		if str, ok := v.(string); ok {
   952  			return []byte(str), nil
   953  		}
   954  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting bytes, got %s", mc, valueKind(v))
   955  	case descriptorpb.FieldDescriptorProto_TYPE_STRING:
   956  		if str, ok := v.(string); ok {
   957  			return str, nil
   958  		}
   959  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting string, got %s", mc, valueKind(v))
   960  	case descriptorpb.FieldDescriptorProto_TYPE_INT32, descriptorpb.FieldDescriptorProto_TYPE_SINT32, descriptorpb.FieldDescriptorProto_TYPE_SFIXED32:
   961  		if i, ok := v.(int64); ok {
   962  			if i > math.MaxInt32 || i < math.MinInt32 {
   963  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int32", mc, i)
   964  			}
   965  			return int32(i), nil
   966  		}
   967  		if ui, ok := v.(uint64); ok {
   968  			if ui > math.MaxInt32 {
   969  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int32", mc, ui)
   970  			}
   971  			return int32(ui), nil
   972  		}
   973  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting int32, got %s", mc, valueKind(v))
   974  	case descriptorpb.FieldDescriptorProto_TYPE_UINT32, descriptorpb.FieldDescriptorProto_TYPE_FIXED32:
   975  		if i, ok := v.(int64); ok {
   976  			if i > math.MaxUint32 || i < 0 {
   977  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint32", mc, i)
   978  			}
   979  			return uint32(i), nil
   980  		}
   981  		if ui, ok := v.(uint64); ok {
   982  			if ui > math.MaxUint32 {
   983  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint32", mc, ui)
   984  			}
   985  			return uint32(ui), nil
   986  		}
   987  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting uint32, got %s", mc, valueKind(v))
   988  	case descriptorpb.FieldDescriptorProto_TYPE_INT64, descriptorpb.FieldDescriptorProto_TYPE_SINT64, descriptorpb.FieldDescriptorProto_TYPE_SFIXED64:
   989  		if i, ok := v.(int64); ok {
   990  			return i, nil
   991  		}
   992  		if ui, ok := v.(uint64); ok {
   993  			if ui > math.MaxInt64 {
   994  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for int64", mc, ui)
   995  			}
   996  			return int64(ui), nil
   997  		}
   998  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting int64, got %s", mc, valueKind(v))
   999  	case descriptorpb.FieldDescriptorProto_TYPE_UINT64, descriptorpb.FieldDescriptorProto_TYPE_FIXED64:
  1000  		if i, ok := v.(int64); ok {
  1001  			if i < 0 {
  1002  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %d is out of range for uint64", mc, i)
  1003  			}
  1004  			return uint64(i), nil
  1005  		}
  1006  		if ui, ok := v.(uint64); ok {
  1007  			return ui, nil
  1008  		}
  1009  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting uint64, got %s", mc, valueKind(v))
  1010  	case descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:
  1011  		if d, ok := v.(float64); ok {
  1012  			return d, nil
  1013  		}
  1014  		if i, ok := v.(int64); ok {
  1015  			return float64(i), nil
  1016  		}
  1017  		if u, ok := v.(uint64); ok {
  1018  			return float64(u), nil
  1019  		}
  1020  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting double, got %s", mc, valueKind(v))
  1021  	case descriptorpb.FieldDescriptorProto_TYPE_FLOAT:
  1022  		if d, ok := v.(float64); ok {
  1023  			if (d > math.MaxFloat32 || d < -math.MaxFloat32) && !math.IsInf(d, 1) && !math.IsInf(d, -1) && !math.IsNaN(d) {
  1024  				return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vvalue %f is out of range for float", mc, d)
  1025  			}
  1026  			return float32(d), nil
  1027  		}
  1028  		if i, ok := v.(int64); ok {
  1029  			return float32(i), nil
  1030  		}
  1031  		if u, ok := v.(uint64); ok {
  1032  			return float32(u), nil
  1033  		}
  1034  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vexpecting float, got %s", mc, valueKind(v))
  1035  	default:
  1036  		return nil, reporter.Errorf(interp.nodeInfo(val).Start(), "%vunrecognized field type: %s", mc, fldType)
  1037  	}
  1038  }
  1039  
  1040  func descriptorType(m proto.Message) string {
  1041  	switch m := m.(type) {
  1042  	case *descriptorpb.DescriptorProto:
  1043  		return "message"
  1044  	case *descriptorpb.DescriptorProto_ExtensionRange:
  1045  		return "extension range"
  1046  	case *descriptorpb.FieldDescriptorProto:
  1047  		if m.GetExtendee() == "" {
  1048  			return "field"
  1049  		} else {
  1050  			return "extension"
  1051  		}
  1052  	case *descriptorpb.EnumDescriptorProto:
  1053  		return "enum"
  1054  	case *descriptorpb.EnumValueDescriptorProto:
  1055  		return "enum value"
  1056  	case *descriptorpb.ServiceDescriptorProto:
  1057  		return "service"
  1058  	case *descriptorpb.MethodDescriptorProto:
  1059  		return "method"
  1060  	case *descriptorpb.FileDescriptorProto:
  1061  		return "file"
  1062  	default:
  1063  		// shouldn't be possible
  1064  		return fmt.Sprintf("%T", m)
  1065  	}
  1066  }