...

Source file src/google.golang.org/protobuf/reflect/protodesc/desc_init.go

Documentation: google.golang.org/protobuf/reflect/protodesc

     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 protodesc
     6  
     7  import (
     8  	"google.golang.org/protobuf/internal/errors"
     9  	"google.golang.org/protobuf/internal/filedesc"
    10  	"google.golang.org/protobuf/internal/strs"
    11  	"google.golang.org/protobuf/proto"
    12  	"google.golang.org/protobuf/reflect/protoreflect"
    13  
    14  	"google.golang.org/protobuf/types/descriptorpb"
    15  )
    16  
    17  type descsByName map[protoreflect.FullName]protoreflect.Descriptor
    18  
    19  func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) {
    20  	es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers
    21  	for i, ed := range eds {
    22  		e := &es[i]
    23  		e.L2 = new(filedesc.EnumL2)
    24  		if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil {
    25  			return nil, err
    26  		}
    27  		if opts := ed.GetOptions(); opts != nil {
    28  			opts = proto.Clone(opts).(*descriptorpb.EnumOptions)
    29  			e.L2.Options = func() protoreflect.ProtoMessage { return opts }
    30  		}
    31  		e.L1.EditionFeatures = mergeEditionFeatures(parent, ed.GetOptions().GetFeatures())
    32  		for _, s := range ed.GetReservedName() {
    33  			e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s))
    34  		}
    35  		for _, rr := range ed.GetReservedRange() {
    36  			e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{
    37  				protoreflect.EnumNumber(rr.GetStart()),
    38  				protoreflect.EnumNumber(rr.GetEnd()),
    39  			})
    40  		}
    41  		if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil {
    42  			return nil, err
    43  		}
    44  	}
    45  	return es, nil
    46  }
    47  
    48  func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) {
    49  	vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers
    50  	for i, vd := range vds {
    51  		v := &vs[i]
    52  		if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil {
    53  			return nil, err
    54  		}
    55  		if opts := vd.GetOptions(); opts != nil {
    56  			opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions)
    57  			v.L1.Options = func() protoreflect.ProtoMessage { return opts }
    58  		}
    59  		v.L1.Number = protoreflect.EnumNumber(vd.GetNumber())
    60  	}
    61  	return vs, nil
    62  }
    63  
    64  func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) {
    65  	ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers
    66  	for i, md := range mds {
    67  		m := &ms[i]
    68  		m.L2 = new(filedesc.MessageL2)
    69  		if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
    70  			return nil, err
    71  		}
    72  		m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures())
    73  		if opts := md.GetOptions(); opts != nil {
    74  			opts = proto.Clone(opts).(*descriptorpb.MessageOptions)
    75  			m.L2.Options = func() protoreflect.ProtoMessage { return opts }
    76  			m.L1.IsMapEntry = opts.GetMapEntry()
    77  			m.L1.IsMessageSet = opts.GetMessageSetWireFormat()
    78  		}
    79  		for _, s := range md.GetReservedName() {
    80  			m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s))
    81  		}
    82  		for _, rr := range md.GetReservedRange() {
    83  			m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{
    84  				protoreflect.FieldNumber(rr.GetStart()),
    85  				protoreflect.FieldNumber(rr.GetEnd()),
    86  			})
    87  		}
    88  		for _, xr := range md.GetExtensionRange() {
    89  			m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{
    90  				protoreflect.FieldNumber(xr.GetStart()),
    91  				protoreflect.FieldNumber(xr.GetEnd()),
    92  			})
    93  			var optsFunc func() protoreflect.ProtoMessage
    94  			if opts := xr.GetOptions(); opts != nil {
    95  				opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions)
    96  				optsFunc = func() protoreflect.ProtoMessage { return opts }
    97  			}
    98  			m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc)
    99  		}
   100  		if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil {
   101  			return nil, err
   102  		}
   103  		if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil {
   104  			return nil, err
   105  		}
   106  		if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil {
   107  			return nil, err
   108  		}
   109  		if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil {
   110  			return nil, err
   111  		}
   112  		if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil {
   113  			return nil, err
   114  		}
   115  	}
   116  	return ms, nil
   117  }
   118  
   119  // canBePacked returns whether the field can use packed encoding:
   120  // https://protobuf.dev/programming-guides/encoding/#packed
   121  func canBePacked(fd *descriptorpb.FieldDescriptorProto) bool {
   122  	if fd.GetLabel() != descriptorpb.FieldDescriptorProto_LABEL_REPEATED {
   123  		return false // not a repeated field
   124  	}
   125  
   126  	switch protoreflect.Kind(fd.GetType()) {
   127  	case protoreflect.MessageKind, protoreflect.GroupKind:
   128  		return false // not a scalar type field
   129  
   130  	case protoreflect.StringKind, protoreflect.BytesKind:
   131  		// string and bytes can explicitly not be declared as packed,
   132  		// see https://protobuf.dev/programming-guides/encoding/#packed
   133  		return false
   134  
   135  	default:
   136  		return true
   137  	}
   138  }
   139  
   140  func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) {
   141  	fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers
   142  	for i, fd := range fds {
   143  		f := &fs[i]
   144  		if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil {
   145  			return nil, err
   146  		}
   147  		f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures())
   148  		f.L1.IsProto3Optional = fd.GetProto3Optional()
   149  		if opts := fd.GetOptions(); opts != nil {
   150  			opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
   151  			f.L1.Options = func() protoreflect.ProtoMessage { return opts }
   152  			f.L1.IsWeak = opts.GetWeak()
   153  			if opts.Packed != nil {
   154  				f.L1.EditionFeatures.IsPacked = opts.GetPacked()
   155  			}
   156  		}
   157  		f.L1.Number = protoreflect.FieldNumber(fd.GetNumber())
   158  		f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel())
   159  		if fd.Type != nil {
   160  			f.L1.Kind = protoreflect.Kind(fd.GetType())
   161  		}
   162  		if fd.JsonName != nil {
   163  			f.L1.StringName.InitJSON(fd.GetJsonName())
   164  		}
   165  
   166  		if f.L1.EditionFeatures.IsLegacyRequired {
   167  			f.L1.Cardinality = protoreflect.Required
   168  		}
   169  
   170  		if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded {
   171  			f.L1.Kind = protoreflect.GroupKind
   172  		}
   173  	}
   174  	return fs, nil
   175  }
   176  
   177  func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) {
   178  	os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers
   179  	for i, od := range ods {
   180  		o := &os[i]
   181  		if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil {
   182  			return nil, err
   183  		}
   184  		o.L1.EditionFeatures = mergeEditionFeatures(parent, od.GetOptions().GetFeatures())
   185  		if opts := od.GetOptions(); opts != nil {
   186  			opts = proto.Clone(opts).(*descriptorpb.OneofOptions)
   187  			o.L1.Options = func() protoreflect.ProtoMessage { return opts }
   188  		}
   189  	}
   190  	return os, nil
   191  }
   192  
   193  func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) {
   194  	xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers
   195  	for i, xd := range xds {
   196  		x := &xs[i]
   197  		x.L2 = new(filedesc.ExtensionL2)
   198  		if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil {
   199  			return nil, err
   200  		}
   201  		x.L1.EditionFeatures = mergeEditionFeatures(parent, xd.GetOptions().GetFeatures())
   202  		if opts := xd.GetOptions(); opts != nil {
   203  			opts = proto.Clone(opts).(*descriptorpb.FieldOptions)
   204  			x.L2.Options = func() protoreflect.ProtoMessage { return opts }
   205  			if opts.Packed != nil {
   206  				x.L1.EditionFeatures.IsPacked = opts.GetPacked()
   207  			}
   208  		}
   209  		x.L1.Number = protoreflect.FieldNumber(xd.GetNumber())
   210  		x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel())
   211  		if xd.Type != nil {
   212  			x.L1.Kind = protoreflect.Kind(xd.GetType())
   213  		}
   214  		if xd.JsonName != nil {
   215  			x.L2.StringName.InitJSON(xd.GetJsonName())
   216  		}
   217  	}
   218  	return xs, nil
   219  }
   220  
   221  func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) {
   222  	ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers
   223  	for i, sd := range sds {
   224  		s := &ss[i]
   225  		s.L2 = new(filedesc.ServiceL2)
   226  		if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil {
   227  			return nil, err
   228  		}
   229  		if opts := sd.GetOptions(); opts != nil {
   230  			opts = proto.Clone(opts).(*descriptorpb.ServiceOptions)
   231  			s.L2.Options = func() protoreflect.ProtoMessage { return opts }
   232  		}
   233  		if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil {
   234  			return nil, err
   235  		}
   236  	}
   237  	return ss, nil
   238  }
   239  
   240  func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) {
   241  	ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers
   242  	for i, md := range mds {
   243  		m := &ms[i]
   244  		if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil {
   245  			return nil, err
   246  		}
   247  		if opts := md.GetOptions(); opts != nil {
   248  			opts = proto.Clone(opts).(*descriptorpb.MethodOptions)
   249  			m.L1.Options = func() protoreflect.ProtoMessage { return opts }
   250  		}
   251  		m.L1.IsStreamingClient = md.GetClientStreaming()
   252  		m.L1.IsStreamingServer = md.GetServerStreaming()
   253  	}
   254  	return ms, nil
   255  }
   256  
   257  func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) {
   258  	if !protoreflect.Name(name).IsValid() {
   259  		return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name)
   260  	}
   261  
   262  	// Derive the full name of the child.
   263  	// Note that enum values are a sibling to the enum parent in the namespace.
   264  	var fullName protoreflect.FullName
   265  	if _, ok := parent.(protoreflect.EnumDescriptor); ok {
   266  		fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name))
   267  	} else {
   268  		fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name))
   269  	}
   270  	if _, ok := r[fullName]; ok {
   271  		return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName)
   272  	}
   273  	r[fullName] = child
   274  
   275  	// TODO: Verify that the full name does not already exist in the resolver?
   276  	// This is not as critical since most usages of NewFile will register
   277  	// the created file back into the registry, which will perform this check.
   278  
   279  	return filedesc.BaseL0{
   280  		FullName:   fullName,
   281  		ParentFile: parent.ParentFile().(*filedesc.File),
   282  		Parent:     parent,
   283  		Index:      idx,
   284  	}, nil
   285  }
   286  

View as plain text