github.com/bakjos/protoreflect@v1.9.2/desc/protoparse/descriptor_protos.go (about)

     1  package protoparse
     2  
     3  import (
     4  	"bytes"
     5  	"math"
     6  	"strings"
     7  	"unicode"
     8  
     9  	"github.com/golang/protobuf/proto"
    10  	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
    11  
    12  	"github.com/bakjos/protoreflect/desc/internal"
    13  	"github.com/bakjos/protoreflect/desc/protoparse/ast"
    14  )
    15  
    16  func (r *parseResult) createFileDescriptor(filename string, file *ast.FileNode) {
    17  	fd := &dpb.FileDescriptorProto{Name: proto.String(filename)}
    18  	r.fd = fd
    19  	r.putFileNode(fd, file)
    20  
    21  	isProto3 := false
    22  	if file.Syntax != nil {
    23  		if file.Syntax.Syntax.AsString() == "proto3" {
    24  			isProto3 = true
    25  		} else if file.Syntax.Syntax.AsString() != "proto2" {
    26  			if r.errs.handleErrorWithPos(file.Syntax.Syntax.Start(), `syntax value must be "proto2" or "proto3"`) != nil {
    27  				return
    28  			}
    29  		}
    30  
    31  		// proto2 is the default, so no need to set unless proto3
    32  		if isProto3 {
    33  			fd.Syntax = proto.String(file.Syntax.Syntax.AsString())
    34  		}
    35  	} else {
    36  		r.errs.warn(file.Start(), ErrNoSyntax)
    37  	}
    38  
    39  	for _, decl := range file.Decls {
    40  		if r.errs.err != nil {
    41  			return
    42  		}
    43  		switch decl := decl.(type) {
    44  		case *ast.EnumNode:
    45  			fd.EnumType = append(fd.EnumType, r.asEnumDescriptor(decl))
    46  		case *ast.ExtendNode:
    47  			r.addExtensions(decl, &fd.Extension, &fd.MessageType, isProto3)
    48  		case *ast.ImportNode:
    49  			index := len(fd.Dependency)
    50  			fd.Dependency = append(fd.Dependency, decl.Name.AsString())
    51  			if decl.Public != nil {
    52  				fd.PublicDependency = append(fd.PublicDependency, int32(index))
    53  			} else if decl.Weak != nil {
    54  				fd.WeakDependency = append(fd.WeakDependency, int32(index))
    55  			}
    56  		case *ast.MessageNode:
    57  			fd.MessageType = append(fd.MessageType, r.asMessageDescriptor(decl, isProto3))
    58  		case *ast.OptionNode:
    59  			if fd.Options == nil {
    60  				fd.Options = &dpb.FileOptions{}
    61  			}
    62  			fd.Options.UninterpretedOption = append(fd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
    63  		case *ast.ServiceNode:
    64  			fd.Service = append(fd.Service, r.asServiceDescriptor(decl))
    65  		case *ast.PackageNode:
    66  			if fd.Package != nil {
    67  				if r.errs.handleErrorWithPos(decl.Start(), "files should have only one package declaration") != nil {
    68  					return
    69  				}
    70  			}
    71  			fd.Package = proto.String(string(decl.Name.AsIdentifier()))
    72  		}
    73  	}
    74  }
    75  
    76  func (r *parseResult) asUninterpretedOptions(nodes []*ast.OptionNode) []*dpb.UninterpretedOption {
    77  	if len(nodes) == 0 {
    78  		return nil
    79  	}
    80  	opts := make([]*dpb.UninterpretedOption, len(nodes))
    81  	for i, n := range nodes {
    82  		opts[i] = r.asUninterpretedOption(n)
    83  	}
    84  	return opts
    85  }
    86  
    87  func (r *parseResult) asUninterpretedOption(node *ast.OptionNode) *dpb.UninterpretedOption {
    88  	opt := &dpb.UninterpretedOption{Name: r.asUninterpretedOptionName(node.Name.Parts)}
    89  	r.putOptionNode(opt, node)
    90  
    91  	switch val := node.Val.Value().(type) {
    92  	case bool:
    93  		if val {
    94  			opt.IdentifierValue = proto.String("true")
    95  		} else {
    96  			opt.IdentifierValue = proto.String("false")
    97  		}
    98  	case int64:
    99  		opt.NegativeIntValue = proto.Int64(val)
   100  	case uint64:
   101  		opt.PositiveIntValue = proto.Uint64(val)
   102  	case float64:
   103  		opt.DoubleValue = proto.Float64(val)
   104  	case string:
   105  		opt.StringValue = []byte(val)
   106  	case ast.Identifier:
   107  		opt.IdentifierValue = proto.String(string(val))
   108  	case []*ast.MessageFieldNode:
   109  		var buf bytes.Buffer
   110  		aggToString(val, &buf)
   111  		aggStr := buf.String()
   112  		opt.AggregateValue = proto.String(aggStr)
   113  		//the grammar does not allow arrays here, so no case for []ast.ValueNode
   114  	}
   115  	return opt
   116  }
   117  
   118  func (r *parseResult) asUninterpretedOptionName(parts []*ast.FieldReferenceNode) []*dpb.UninterpretedOption_NamePart {
   119  	ret := make([]*dpb.UninterpretedOption_NamePart, len(parts))
   120  	for i, part := range parts {
   121  		np := &dpb.UninterpretedOption_NamePart{
   122  			NamePart:    proto.String(string(part.Name.AsIdentifier())),
   123  			IsExtension: proto.Bool(part.IsExtension()),
   124  		}
   125  		r.putOptionNamePartNode(np, part)
   126  		ret[i] = np
   127  	}
   128  	return ret
   129  }
   130  
   131  func (r *parseResult) addExtensions(ext *ast.ExtendNode, flds *[]*dpb.FieldDescriptorProto, msgs *[]*dpb.DescriptorProto, isProto3 bool) {
   132  	extendee := string(ext.Extendee.AsIdentifier())
   133  	count := 0
   134  	for _, decl := range ext.Decls {
   135  		switch decl := decl.(type) {
   136  		case *ast.FieldNode:
   137  			count++
   138  			// use higher limit since we don't know yet whether extendee is messageset wire format
   139  			fd := r.asFieldDescriptor(decl, internal.MaxTag, isProto3)
   140  			fd.Extendee = proto.String(extendee)
   141  			*flds = append(*flds, fd)
   142  		case *ast.GroupNode:
   143  			count++
   144  			// ditto: use higher limit right now
   145  			fd, md := r.asGroupDescriptors(decl, isProto3, internal.MaxTag)
   146  			fd.Extendee = proto.String(extendee)
   147  			*flds = append(*flds, fd)
   148  			*msgs = append(*msgs, md)
   149  		}
   150  	}
   151  	if count == 0 {
   152  		_ = r.errs.handleErrorWithPos(ext.Start(), "extend sections must define at least one extension")
   153  	}
   154  }
   155  
   156  func asLabel(lbl *ast.FieldLabel) *dpb.FieldDescriptorProto_Label {
   157  	if !lbl.IsPresent() {
   158  		return nil
   159  	}
   160  	switch {
   161  	case lbl.Repeated:
   162  		return dpb.FieldDescriptorProto_LABEL_REPEATED.Enum()
   163  	case lbl.Required:
   164  		return dpb.FieldDescriptorProto_LABEL_REQUIRED.Enum()
   165  	default:
   166  		return dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
   167  	}
   168  }
   169  
   170  func (r *parseResult) asFieldDescriptor(node *ast.FieldNode, maxTag int32, isProto3 bool) *dpb.FieldDescriptorProto {
   171  	tag := node.Tag.Val
   172  	if err := checkTag(node.Tag.Start(), tag, maxTag); err != nil {
   173  		_ = r.errs.handleError(err)
   174  	}
   175  	fd := newFieldDescriptor(node.Name.Val, string(node.FldType.AsIdentifier()), int32(tag), asLabel(&node.Label))
   176  	r.putFieldNode(fd, node)
   177  	if opts := node.Options.GetElements(); len(opts) > 0 {
   178  		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   179  	}
   180  	if isProto3 && fd.Label != nil && fd.GetLabel() == dpb.FieldDescriptorProto_LABEL_OPTIONAL {
   181  		internal.SetProto3Optional(fd)
   182  	}
   183  	return fd
   184  }
   185  
   186  var fieldTypes = map[string]dpb.FieldDescriptorProto_Type{
   187  	"double":   dpb.FieldDescriptorProto_TYPE_DOUBLE,
   188  	"float":    dpb.FieldDescriptorProto_TYPE_FLOAT,
   189  	"int32":    dpb.FieldDescriptorProto_TYPE_INT32,
   190  	"int64":    dpb.FieldDescriptorProto_TYPE_INT64,
   191  	"uint32":   dpb.FieldDescriptorProto_TYPE_UINT32,
   192  	"uint64":   dpb.FieldDescriptorProto_TYPE_UINT64,
   193  	"sint32":   dpb.FieldDescriptorProto_TYPE_SINT32,
   194  	"sint64":   dpb.FieldDescriptorProto_TYPE_SINT64,
   195  	"fixed32":  dpb.FieldDescriptorProto_TYPE_FIXED32,
   196  	"fixed64":  dpb.FieldDescriptorProto_TYPE_FIXED64,
   197  	"sfixed32": dpb.FieldDescriptorProto_TYPE_SFIXED32,
   198  	"sfixed64": dpb.FieldDescriptorProto_TYPE_SFIXED64,
   199  	"bool":     dpb.FieldDescriptorProto_TYPE_BOOL,
   200  	"string":   dpb.FieldDescriptorProto_TYPE_STRING,
   201  	"bytes":    dpb.FieldDescriptorProto_TYPE_BYTES,
   202  }
   203  
   204  func newFieldDescriptor(name string, fieldType string, tag int32, lbl *dpb.FieldDescriptorProto_Label) *dpb.FieldDescriptorProto {
   205  	fd := &dpb.FieldDescriptorProto{
   206  		Name:     proto.String(name),
   207  		JsonName: proto.String(internal.JsonName(name)),
   208  		Number:   proto.Int32(tag),
   209  		Label:    lbl,
   210  	}
   211  	t, ok := fieldTypes[fieldType]
   212  	if ok {
   213  		fd.Type = t.Enum()
   214  	} else {
   215  		// NB: we don't have enough info to determine whether this is an enum
   216  		// or a message type, so we'll leave Type nil and set it later
   217  		// (during linking)
   218  		fd.TypeName = proto.String(fieldType)
   219  	}
   220  	return fd
   221  }
   222  
   223  func (r *parseResult) asGroupDescriptors(group *ast.GroupNode, isProto3 bool, maxTag int32) (*dpb.FieldDescriptorProto, *dpb.DescriptorProto) {
   224  	tag := group.Tag.Val
   225  	if err := checkTag(group.Tag.Start(), tag, maxTag); err != nil {
   226  		_ = r.errs.handleError(err)
   227  	}
   228  	if !unicode.IsUpper(rune(group.Name.Val[0])) {
   229  		_ = r.errs.handleErrorWithPos(group.Name.Start(), "group %s should have a name that starts with a capital letter", group.Name.Val)
   230  	}
   231  	fieldName := strings.ToLower(group.Name.Val)
   232  	fd := &dpb.FieldDescriptorProto{
   233  		Name:     proto.String(fieldName),
   234  		JsonName: proto.String(internal.JsonName(fieldName)),
   235  		Number:   proto.Int32(int32(tag)),
   236  		Label:    asLabel(&group.Label),
   237  		Type:     dpb.FieldDescriptorProto_TYPE_GROUP.Enum(),
   238  		TypeName: proto.String(group.Name.Val),
   239  	}
   240  	r.putFieldNode(fd, group)
   241  	if opts := group.Options.GetElements(); len(opts) > 0 {
   242  		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   243  	}
   244  	md := &dpb.DescriptorProto{Name: proto.String(group.Name.Val)}
   245  	r.putMessageNode(md, group)
   246  	r.addMessageBody(md, &group.MessageBody, isProto3)
   247  	return fd, md
   248  }
   249  
   250  func (r *parseResult) asMapDescriptors(mapField *ast.MapFieldNode, isProto3 bool, maxTag int32) (*dpb.FieldDescriptorProto, *dpb.DescriptorProto) {
   251  	tag := mapField.Tag.Val
   252  	if err := checkTag(mapField.Tag.Start(), tag, maxTag); err != nil {
   253  		_ = r.errs.handleError(err)
   254  	}
   255  	var lbl *dpb.FieldDescriptorProto_Label
   256  	if !isProto3 {
   257  		lbl = dpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum()
   258  	}
   259  	keyFd := newFieldDescriptor("key", mapField.MapType.KeyType.Val, 1, lbl)
   260  	r.putFieldNode(keyFd, mapField.KeyField())
   261  	valFd := newFieldDescriptor("value", string(mapField.MapType.ValueType.AsIdentifier()), 2, lbl)
   262  	r.putFieldNode(valFd, mapField.ValueField())
   263  	entryName := internal.InitCap(internal.JsonName(mapField.Name.Val)) + "Entry"
   264  	fd := newFieldDescriptor(mapField.Name.Val, entryName, int32(tag), dpb.FieldDescriptorProto_LABEL_REPEATED.Enum())
   265  	if opts := mapField.Options.GetElements(); len(opts) > 0 {
   266  		fd.Options = &dpb.FieldOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   267  	}
   268  	r.putFieldNode(fd, mapField)
   269  	md := &dpb.DescriptorProto{
   270  		Name:    proto.String(entryName),
   271  		Options: &dpb.MessageOptions{MapEntry: proto.Bool(true)},
   272  		Field:   []*dpb.FieldDescriptorProto{keyFd, valFd},
   273  	}
   274  	r.putMessageNode(md, mapField)
   275  	return fd, md
   276  }
   277  
   278  func (r *parseResult) asExtensionRanges(node *ast.ExtensionRangeNode, maxTag int32) []*dpb.DescriptorProto_ExtensionRange {
   279  	opts := r.asUninterpretedOptions(node.Options.GetElements())
   280  	ers := make([]*dpb.DescriptorProto_ExtensionRange, len(node.Ranges))
   281  	for i, rng := range node.Ranges {
   282  		start, end := getRangeBounds(r, rng, 0, maxTag)
   283  		er := &dpb.DescriptorProto_ExtensionRange{
   284  			Start: proto.Int32(start),
   285  			End:   proto.Int32(end + 1),
   286  		}
   287  		if len(opts) > 0 {
   288  			er.Options = &dpb.ExtensionRangeOptions{UninterpretedOption: opts}
   289  		}
   290  		r.putExtensionRangeNode(er, rng)
   291  		ers[i] = er
   292  	}
   293  	return ers
   294  }
   295  
   296  func (r *parseResult) asEnumValue(ev *ast.EnumValueNode) *dpb.EnumValueDescriptorProto {
   297  	num, ok := ast.AsInt32(ev.Number, math.MinInt32, math.MaxInt32)
   298  	if !ok {
   299  		_ = r.errs.handleErrorWithPos(ev.Number.Start(), "value %d is out of range: should be between %d and %d", ev.Number.Value(), math.MinInt32, math.MaxInt32)
   300  	}
   301  	evd := &dpb.EnumValueDescriptorProto{Name: proto.String(ev.Name.Val), Number: proto.Int32(num)}
   302  	r.putEnumValueNode(evd, ev)
   303  	if opts := ev.Options.GetElements(); len(opts) > 0 {
   304  		evd.Options = &dpb.EnumValueOptions{UninterpretedOption: r.asUninterpretedOptions(opts)}
   305  	}
   306  	return evd
   307  }
   308  
   309  func (r *parseResult) asMethodDescriptor(node *ast.RPCNode) *dpb.MethodDescriptorProto {
   310  	md := &dpb.MethodDescriptorProto{
   311  		Name:       proto.String(node.Name.Val),
   312  		InputType:  proto.String(string(node.Input.MessageType.AsIdentifier())),
   313  		OutputType: proto.String(string(node.Output.MessageType.AsIdentifier())),
   314  	}
   315  	r.putMethodNode(md, node)
   316  	if node.Input.Stream != nil {
   317  		md.ClientStreaming = proto.Bool(true)
   318  	}
   319  	if node.Output.Stream != nil {
   320  		md.ServerStreaming = proto.Bool(true)
   321  	}
   322  	// protoc always adds a MethodOptions if there are brackets
   323  	// We do the same to match protoc as closely as possible
   324  	// https://github.com/protocolbuffers/protobuf/blob/0c3f43a6190b77f1f68b7425d1b7e1a8257a8d0c/src/google/protobuf/compiler/parser.cc#L2152
   325  	if node.OpenBrace != nil {
   326  		md.Options = &dpb.MethodOptions{}
   327  		for _, decl := range node.Decls {
   328  			switch decl := decl.(type) {
   329  			case *ast.OptionNode:
   330  				md.Options.UninterpretedOption = append(md.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   331  			}
   332  		}
   333  	}
   334  	return md
   335  }
   336  
   337  func (r *parseResult) asEnumDescriptor(en *ast.EnumNode) *dpb.EnumDescriptorProto {
   338  	ed := &dpb.EnumDescriptorProto{Name: proto.String(en.Name.Val)}
   339  	r.putEnumNode(ed, en)
   340  	for _, decl := range en.Decls {
   341  		switch decl := decl.(type) {
   342  		case *ast.OptionNode:
   343  			if ed.Options == nil {
   344  				ed.Options = &dpb.EnumOptions{}
   345  			}
   346  			ed.Options.UninterpretedOption = append(ed.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   347  		case *ast.EnumValueNode:
   348  			ed.Value = append(ed.Value, r.asEnumValue(decl))
   349  		case *ast.ReservedNode:
   350  			for _, n := range decl.Names {
   351  				ed.ReservedName = append(ed.ReservedName, n.AsString())
   352  			}
   353  			for _, rng := range decl.Ranges {
   354  				ed.ReservedRange = append(ed.ReservedRange, r.asEnumReservedRange(rng))
   355  			}
   356  		}
   357  	}
   358  	return ed
   359  }
   360  
   361  func (r *parseResult) asEnumReservedRange(rng *ast.RangeNode) *dpb.EnumDescriptorProto_EnumReservedRange {
   362  	start, end := getRangeBounds(r, rng, math.MinInt32, math.MaxInt32)
   363  	rr := &dpb.EnumDescriptorProto_EnumReservedRange{
   364  		Start: proto.Int32(start),
   365  		End:   proto.Int32(end),
   366  	}
   367  	r.putEnumReservedRangeNode(rr, rng)
   368  	return rr
   369  }
   370  
   371  func (r *parseResult) asMessageDescriptor(node *ast.MessageNode, isProto3 bool) *dpb.DescriptorProto {
   372  	msgd := &dpb.DescriptorProto{Name: proto.String(node.Name.Val)}
   373  	r.putMessageNode(msgd, node)
   374  	r.addMessageBody(msgd, &node.MessageBody, isProto3)
   375  	return msgd
   376  }
   377  
   378  func (r *parseResult) addMessageBody(msgd *dpb.DescriptorProto, body *ast.MessageBody, isProto3 bool) {
   379  	// first process any options
   380  	for _, decl := range body.Decls {
   381  		if opt, ok := decl.(*ast.OptionNode); ok {
   382  			if msgd.Options == nil {
   383  				msgd.Options = &dpb.MessageOptions{}
   384  			}
   385  			msgd.Options.UninterpretedOption = append(msgd.Options.UninterpretedOption, r.asUninterpretedOption(opt))
   386  		}
   387  	}
   388  
   389  	// now that we have options, we can see if this uses messageset wire format, which
   390  	// impacts how we validate tag numbers in any fields in the message
   391  	maxTag := int32(internal.MaxNormalTag)
   392  	messageSetOpt, err := isMessageSetWireFormat(r, "message "+msgd.GetName(), msgd)
   393  	if err != nil {
   394  		return
   395  	} else if messageSetOpt != nil {
   396  		maxTag = internal.MaxTag // higher limit for messageset wire format
   397  	}
   398  
   399  	rsvdNames := map[string]int{}
   400  
   401  	// now we can process the rest
   402  	for _, decl := range body.Decls {
   403  		switch decl := decl.(type) {
   404  		case *ast.EnumNode:
   405  			msgd.EnumType = append(msgd.EnumType, r.asEnumDescriptor(decl))
   406  		case *ast.ExtendNode:
   407  			r.addExtensions(decl, &msgd.Extension, &msgd.NestedType, isProto3)
   408  		case *ast.ExtensionRangeNode:
   409  			msgd.ExtensionRange = append(msgd.ExtensionRange, r.asExtensionRanges(decl, maxTag)...)
   410  		case *ast.FieldNode:
   411  			fd := r.asFieldDescriptor(decl, maxTag, isProto3)
   412  			msgd.Field = append(msgd.Field, fd)
   413  		case *ast.MapFieldNode:
   414  			fd, md := r.asMapDescriptors(decl, isProto3, maxTag)
   415  			msgd.Field = append(msgd.Field, fd)
   416  			msgd.NestedType = append(msgd.NestedType, md)
   417  		case *ast.GroupNode:
   418  			fd, md := r.asGroupDescriptors(decl, isProto3, maxTag)
   419  			msgd.Field = append(msgd.Field, fd)
   420  			msgd.NestedType = append(msgd.NestedType, md)
   421  		case *ast.OneOfNode:
   422  			oodIndex := len(msgd.OneofDecl)
   423  			ood := &dpb.OneofDescriptorProto{Name: proto.String(decl.Name.Val)}
   424  			r.putOneOfNode(ood, decl)
   425  			msgd.OneofDecl = append(msgd.OneofDecl, ood)
   426  			ooFields := 0
   427  			for _, oodecl := range decl.Decls {
   428  				switch oodecl := oodecl.(type) {
   429  				case *ast.OptionNode:
   430  					if ood.Options == nil {
   431  						ood.Options = &dpb.OneofOptions{}
   432  					}
   433  					ood.Options.UninterpretedOption = append(ood.Options.UninterpretedOption, r.asUninterpretedOption(oodecl))
   434  				case *ast.FieldNode:
   435  					fd := r.asFieldDescriptor(oodecl, maxTag, isProto3)
   436  					fd.OneofIndex = proto.Int32(int32(oodIndex))
   437  					msgd.Field = append(msgd.Field, fd)
   438  					ooFields++
   439  				case *ast.GroupNode:
   440  					fd, md := r.asGroupDescriptors(oodecl, isProto3, maxTag)
   441  					fd.OneofIndex = proto.Int32(int32(oodIndex))
   442  					msgd.Field = append(msgd.Field, fd)
   443  					msgd.NestedType = append(msgd.NestedType, md)
   444  					ooFields++
   445  				}
   446  			}
   447  			if ooFields == 0 {
   448  				_ = r.errs.handleErrorWithPos(decl.Start(), "oneof must contain at least one field")
   449  			}
   450  		case *ast.MessageNode:
   451  			msgd.NestedType = append(msgd.NestedType, r.asMessageDescriptor(decl, isProto3))
   452  		case *ast.ReservedNode:
   453  			for _, n := range decl.Names {
   454  				count := rsvdNames[n.AsString()]
   455  				if count == 1 { // already seen
   456  					_ = r.errs.handleErrorWithPos(n.Start(), "name %q is reserved multiple times", n.AsString())
   457  				}
   458  				rsvdNames[n.AsString()] = count + 1
   459  				msgd.ReservedName = append(msgd.ReservedName, n.AsString())
   460  			}
   461  			for _, rng := range decl.Ranges {
   462  				msgd.ReservedRange = append(msgd.ReservedRange, r.asMessageReservedRange(rng, maxTag))
   463  			}
   464  		}
   465  	}
   466  
   467  	if messageSetOpt != nil {
   468  		if len(msgd.Field) > 0 {
   469  			node := r.getFieldNode(msgd.Field[0])
   470  			_ = r.errs.handleErrorWithPos(node.Start(), "messages with message-set wire format cannot contain non-extension fields")
   471  		}
   472  		if len(msgd.ExtensionRange) == 0 {
   473  			node := r.getOptionNode(messageSetOpt)
   474  			_ = r.errs.handleErrorWithPos(node.Start(), "messages with message-set wire format must contain at least one extension range")
   475  		}
   476  	}
   477  
   478  	// process any proto3_optional fields
   479  	if isProto3 {
   480  		internal.ProcessProto3OptionalFields(msgd)
   481  	}
   482  }
   483  
   484  func isMessageSetWireFormat(res *parseResult, scope string, md *dpb.DescriptorProto) (*dpb.UninterpretedOption, error) {
   485  	uo := md.GetOptions().GetUninterpretedOption()
   486  	index, err := findOption(res, scope, uo, "message_set_wire_format")
   487  	if err != nil {
   488  		return nil, err
   489  	}
   490  	if index == -1 {
   491  		// no such option
   492  		return nil, nil
   493  	}
   494  
   495  	opt := uo[index]
   496  
   497  	switch opt.GetIdentifierValue() {
   498  	case "true":
   499  		return opt, nil
   500  	case "false":
   501  		return nil, nil
   502  	default:
   503  		optNode := res.getOptionNode(opt)
   504  		return nil, res.errs.handleErrorWithPos(optNode.GetValue().Start(), "%s: expecting bool value for message_set_wire_format option", scope)
   505  	}
   506  }
   507  
   508  func (r *parseResult) asMessageReservedRange(rng *ast.RangeNode, maxTag int32) *dpb.DescriptorProto_ReservedRange {
   509  	start, end := getRangeBounds(r, rng, 0, maxTag)
   510  	rr := &dpb.DescriptorProto_ReservedRange{
   511  		Start: proto.Int32(start),
   512  		End:   proto.Int32(end + 1),
   513  	}
   514  	r.putMessageReservedRangeNode(rr, rng)
   515  	return rr
   516  }
   517  
   518  func getRangeBounds(res *parseResult, rng *ast.RangeNode, minVal, maxVal int32) (int32, int32) {
   519  	checkOrder := true
   520  	start, ok := rng.StartValueAsInt32(minVal, maxVal)
   521  	if !ok {
   522  		checkOrder = false
   523  		_ = res.errs.handleErrorWithPos(rng.StartVal.Start(), "range start %d is out of range: should be between %d and %d", rng.StartValue(), minVal, maxVal)
   524  	}
   525  
   526  	end, ok := rng.EndValueAsInt32(minVal, maxVal)
   527  	if !ok {
   528  		checkOrder = false
   529  		if rng.EndVal != nil {
   530  			_ = res.errs.handleErrorWithPos(rng.EndVal.Start(), "range end %d is out of range: should be between %d and %d", rng.EndValue(), minVal, maxVal)
   531  		}
   532  	}
   533  
   534  	if checkOrder && start > end {
   535  		_ = res.errs.handleErrorWithPos(rng.RangeStart().Start(), "range, %d to %d, is invalid: start must be <= end", start, end)
   536  	}
   537  
   538  	return start, end
   539  }
   540  
   541  func (r *parseResult) asServiceDescriptor(svc *ast.ServiceNode) *dpb.ServiceDescriptorProto {
   542  	sd := &dpb.ServiceDescriptorProto{Name: proto.String(svc.Name.Val)}
   543  	r.putServiceNode(sd, svc)
   544  	for _, decl := range svc.Decls {
   545  		switch decl := decl.(type) {
   546  		case *ast.OptionNode:
   547  			if sd.Options == nil {
   548  				sd.Options = &dpb.ServiceOptions{}
   549  			}
   550  			sd.Options.UninterpretedOption = append(sd.Options.UninterpretedOption, r.asUninterpretedOption(decl))
   551  		case *ast.RPCNode:
   552  			sd.Method = append(sd.Method, r.asMethodDescriptor(decl))
   553  		}
   554  	}
   555  	return sd
   556  }