...

Source file src/google.golang.org/protobuf/internal/filedesc/desc_init.go

Documentation: google.golang.org/protobuf/internal/filedesc

     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 filedesc
     6  
     7  import (
     8  	"sync"
     9  
    10  	"google.golang.org/protobuf/encoding/protowire"
    11  	"google.golang.org/protobuf/internal/genid"
    12  	"google.golang.org/protobuf/internal/strs"
    13  	"google.golang.org/protobuf/reflect/protoreflect"
    14  )
    15  
    16  // fileRaw is a data struct used when initializing a file descriptor from
    17  // a raw FileDescriptorProto.
    18  type fileRaw struct {
    19  	builder       Builder
    20  	allEnums      []Enum
    21  	allMessages   []Message
    22  	allExtensions []Extension
    23  	allServices   []Service
    24  }
    25  
    26  func newRawFile(db Builder) *File {
    27  	fd := &File{fileRaw: fileRaw{builder: db}}
    28  	fd.initDecls(db.NumEnums, db.NumMessages, db.NumExtensions, db.NumServices)
    29  	fd.unmarshalSeed(db.RawDescriptor)
    30  
    31  	// Extended message targets are eagerly resolved since registration
    32  	// needs this information at program init time.
    33  	for i := range fd.allExtensions {
    34  		xd := &fd.allExtensions[i]
    35  		xd.L1.Extendee = fd.resolveMessageDependency(xd.L1.Extendee, listExtTargets, int32(i))
    36  	}
    37  
    38  	fd.checkDecls()
    39  	return fd
    40  }
    41  
    42  // initDecls pre-allocates slices for the exact number of enums, messages
    43  // (including map entries), extensions, and services declared in the proto file.
    44  // This is done to avoid regrowing the slice, which would change the address
    45  // for any previously seen declaration.
    46  //
    47  // The alloc methods "allocates" slices by pulling from the capacity.
    48  func (fd *File) initDecls(numEnums, numMessages, numExtensions, numServices int32) {
    49  	fd.allEnums = make([]Enum, 0, numEnums)
    50  	fd.allMessages = make([]Message, 0, numMessages)
    51  	fd.allExtensions = make([]Extension, 0, numExtensions)
    52  	fd.allServices = make([]Service, 0, numServices)
    53  }
    54  
    55  func (fd *File) allocEnums(n int) []Enum {
    56  	total := len(fd.allEnums)
    57  	es := fd.allEnums[total : total+n]
    58  	fd.allEnums = fd.allEnums[:total+n]
    59  	return es
    60  }
    61  func (fd *File) allocMessages(n int) []Message {
    62  	total := len(fd.allMessages)
    63  	ms := fd.allMessages[total : total+n]
    64  	fd.allMessages = fd.allMessages[:total+n]
    65  	return ms
    66  }
    67  func (fd *File) allocExtensions(n int) []Extension {
    68  	total := len(fd.allExtensions)
    69  	xs := fd.allExtensions[total : total+n]
    70  	fd.allExtensions = fd.allExtensions[:total+n]
    71  	return xs
    72  }
    73  func (fd *File) allocServices(n int) []Service {
    74  	total := len(fd.allServices)
    75  	xs := fd.allServices[total : total+n]
    76  	fd.allServices = fd.allServices[:total+n]
    77  	return xs
    78  }
    79  
    80  // checkDecls performs a sanity check that the expected number of expected
    81  // declarations matches the number that were found in the descriptor proto.
    82  func (fd *File) checkDecls() {
    83  	switch {
    84  	case len(fd.allEnums) != cap(fd.allEnums):
    85  	case len(fd.allMessages) != cap(fd.allMessages):
    86  	case len(fd.allExtensions) != cap(fd.allExtensions):
    87  	case len(fd.allServices) != cap(fd.allServices):
    88  	default:
    89  		return
    90  	}
    91  	panic("mismatching cardinality")
    92  }
    93  
    94  func (fd *File) unmarshalSeed(b []byte) {
    95  	sb := getBuilder()
    96  	defer putBuilder(sb)
    97  
    98  	var prevField protoreflect.FieldNumber
    99  	var numEnums, numMessages, numExtensions, numServices int
   100  	var posEnums, posMessages, posExtensions, posServices int
   101  	b0 := b
   102  	for len(b) > 0 {
   103  		num, typ, n := protowire.ConsumeTag(b)
   104  		b = b[n:]
   105  		switch typ {
   106  		case protowire.BytesType:
   107  			v, m := protowire.ConsumeBytes(b)
   108  			b = b[m:]
   109  			switch num {
   110  			case genid.FileDescriptorProto_Syntax_field_number:
   111  				switch string(v) {
   112  				case "proto2":
   113  					fd.L1.Syntax = protoreflect.Proto2
   114  				case "proto3":
   115  					fd.L1.Syntax = protoreflect.Proto3
   116  				default:
   117  					panic("invalid syntax")
   118  				}
   119  			case genid.FileDescriptorProto_Name_field_number:
   120  				fd.L1.Path = sb.MakeString(v)
   121  			case genid.FileDescriptorProto_Package_field_number:
   122  				fd.L1.Package = protoreflect.FullName(sb.MakeString(v))
   123  			case genid.FileDescriptorProto_EnumType_field_number:
   124  				if prevField != genid.FileDescriptorProto_EnumType_field_number {
   125  					if numEnums > 0 {
   126  						panic("non-contiguous repeated field")
   127  					}
   128  					posEnums = len(b0) - len(b) - n - m
   129  				}
   130  				numEnums++
   131  			case genid.FileDescriptorProto_MessageType_field_number:
   132  				if prevField != genid.FileDescriptorProto_MessageType_field_number {
   133  					if numMessages > 0 {
   134  						panic("non-contiguous repeated field")
   135  					}
   136  					posMessages = len(b0) - len(b) - n - m
   137  				}
   138  				numMessages++
   139  			case genid.FileDescriptorProto_Extension_field_number:
   140  				if prevField != genid.FileDescriptorProto_Extension_field_number {
   141  					if numExtensions > 0 {
   142  						panic("non-contiguous repeated field")
   143  					}
   144  					posExtensions = len(b0) - len(b) - n - m
   145  				}
   146  				numExtensions++
   147  			case genid.FileDescriptorProto_Service_field_number:
   148  				if prevField != genid.FileDescriptorProto_Service_field_number {
   149  					if numServices > 0 {
   150  						panic("non-contiguous repeated field")
   151  					}
   152  					posServices = len(b0) - len(b) - n - m
   153  				}
   154  				numServices++
   155  			}
   156  			prevField = num
   157  		default:
   158  			m := protowire.ConsumeFieldValue(num, typ, b)
   159  			b = b[m:]
   160  			prevField = -1 // ignore known field numbers of unknown wire type
   161  		}
   162  	}
   163  
   164  	// If syntax is missing, it is assumed to be proto2.
   165  	if fd.L1.Syntax == 0 {
   166  		fd.L1.Syntax = protoreflect.Proto2
   167  	}
   168  
   169  	// Must allocate all declarations before parsing each descriptor type
   170  	// to ensure we handled all descriptors in "flattened ordering".
   171  	if numEnums > 0 {
   172  		fd.L1.Enums.List = fd.allocEnums(numEnums)
   173  	}
   174  	if numMessages > 0 {
   175  		fd.L1.Messages.List = fd.allocMessages(numMessages)
   176  	}
   177  	if numExtensions > 0 {
   178  		fd.L1.Extensions.List = fd.allocExtensions(numExtensions)
   179  	}
   180  	if numServices > 0 {
   181  		fd.L1.Services.List = fd.allocServices(numServices)
   182  	}
   183  
   184  	if numEnums > 0 {
   185  		b := b0[posEnums:]
   186  		for i := range fd.L1.Enums.List {
   187  			_, n := protowire.ConsumeVarint(b)
   188  			v, m := protowire.ConsumeBytes(b[n:])
   189  			fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i)
   190  			b = b[n+m:]
   191  		}
   192  	}
   193  	if numMessages > 0 {
   194  		b := b0[posMessages:]
   195  		for i := range fd.L1.Messages.List {
   196  			_, n := protowire.ConsumeVarint(b)
   197  			v, m := protowire.ConsumeBytes(b[n:])
   198  			fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i)
   199  			b = b[n+m:]
   200  		}
   201  	}
   202  	if numExtensions > 0 {
   203  		b := b0[posExtensions:]
   204  		for i := range fd.L1.Extensions.List {
   205  			_, n := protowire.ConsumeVarint(b)
   206  			v, m := protowire.ConsumeBytes(b[n:])
   207  			fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i)
   208  			b = b[n+m:]
   209  		}
   210  	}
   211  	if numServices > 0 {
   212  		b := b0[posServices:]
   213  		for i := range fd.L1.Services.List {
   214  			_, n := protowire.ConsumeVarint(b)
   215  			v, m := protowire.ConsumeBytes(b[n:])
   216  			fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i)
   217  			b = b[n+m:]
   218  		}
   219  	}
   220  }
   221  
   222  func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
   223  	ed.L0.ParentFile = pf
   224  	ed.L0.Parent = pd
   225  	ed.L0.Index = i
   226  
   227  	var numValues int
   228  	for b := b; len(b) > 0; {
   229  		num, typ, n := protowire.ConsumeTag(b)
   230  		b = b[n:]
   231  		switch typ {
   232  		case protowire.BytesType:
   233  			v, m := protowire.ConsumeBytes(b)
   234  			b = b[m:]
   235  			switch num {
   236  			case genid.EnumDescriptorProto_Name_field_number:
   237  				ed.L0.FullName = appendFullName(sb, pd.FullName(), v)
   238  			case genid.EnumDescriptorProto_Value_field_number:
   239  				numValues++
   240  			}
   241  		default:
   242  			m := protowire.ConsumeFieldValue(num, typ, b)
   243  			b = b[m:]
   244  		}
   245  	}
   246  
   247  	// Only construct enum value descriptors for top-level enums since
   248  	// they are needed for registration.
   249  	if pd != pf {
   250  		return
   251  	}
   252  	ed.L1.eagerValues = true
   253  	ed.L2 = new(EnumL2)
   254  	ed.L2.Values.List = make([]EnumValue, numValues)
   255  	for i := 0; len(b) > 0; {
   256  		num, typ, n := protowire.ConsumeTag(b)
   257  		b = b[n:]
   258  		switch typ {
   259  		case protowire.BytesType:
   260  			v, m := protowire.ConsumeBytes(b)
   261  			b = b[m:]
   262  			switch num {
   263  			case genid.EnumDescriptorProto_Value_field_number:
   264  				ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i)
   265  				i++
   266  			}
   267  		default:
   268  			m := protowire.ConsumeFieldValue(num, typ, b)
   269  			b = b[m:]
   270  		}
   271  	}
   272  }
   273  
   274  func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
   275  	md.L0.ParentFile = pf
   276  	md.L0.Parent = pd
   277  	md.L0.Index = i
   278  
   279  	var prevField protoreflect.FieldNumber
   280  	var numEnums, numMessages, numExtensions int
   281  	var posEnums, posMessages, posExtensions int
   282  	b0 := b
   283  	for len(b) > 0 {
   284  		num, typ, n := protowire.ConsumeTag(b)
   285  		b = b[n:]
   286  		switch typ {
   287  		case protowire.BytesType:
   288  			v, m := protowire.ConsumeBytes(b)
   289  			b = b[m:]
   290  			switch num {
   291  			case genid.DescriptorProto_Name_field_number:
   292  				md.L0.FullName = appendFullName(sb, pd.FullName(), v)
   293  			case genid.DescriptorProto_EnumType_field_number:
   294  				if prevField != genid.DescriptorProto_EnumType_field_number {
   295  					if numEnums > 0 {
   296  						panic("non-contiguous repeated field")
   297  					}
   298  					posEnums = len(b0) - len(b) - n - m
   299  				}
   300  				numEnums++
   301  			case genid.DescriptorProto_NestedType_field_number:
   302  				if prevField != genid.DescriptorProto_NestedType_field_number {
   303  					if numMessages > 0 {
   304  						panic("non-contiguous repeated field")
   305  					}
   306  					posMessages = len(b0) - len(b) - n - m
   307  				}
   308  				numMessages++
   309  			case genid.DescriptorProto_Extension_field_number:
   310  				if prevField != genid.DescriptorProto_Extension_field_number {
   311  					if numExtensions > 0 {
   312  						panic("non-contiguous repeated field")
   313  					}
   314  					posExtensions = len(b0) - len(b) - n - m
   315  				}
   316  				numExtensions++
   317  			case genid.DescriptorProto_Options_field_number:
   318  				md.unmarshalSeedOptions(v)
   319  			}
   320  			prevField = num
   321  		default:
   322  			m := protowire.ConsumeFieldValue(num, typ, b)
   323  			b = b[m:]
   324  			prevField = -1 // ignore known field numbers of unknown wire type
   325  		}
   326  	}
   327  
   328  	// Must allocate all declarations before parsing each descriptor type
   329  	// to ensure we handled all descriptors in "flattened ordering".
   330  	if numEnums > 0 {
   331  		md.L1.Enums.List = pf.allocEnums(numEnums)
   332  	}
   333  	if numMessages > 0 {
   334  		md.L1.Messages.List = pf.allocMessages(numMessages)
   335  	}
   336  	if numExtensions > 0 {
   337  		md.L1.Extensions.List = pf.allocExtensions(numExtensions)
   338  	}
   339  
   340  	if numEnums > 0 {
   341  		b := b0[posEnums:]
   342  		for i := range md.L1.Enums.List {
   343  			_, n := protowire.ConsumeVarint(b)
   344  			v, m := protowire.ConsumeBytes(b[n:])
   345  			md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i)
   346  			b = b[n+m:]
   347  		}
   348  	}
   349  	if numMessages > 0 {
   350  		b := b0[posMessages:]
   351  		for i := range md.L1.Messages.List {
   352  			_, n := protowire.ConsumeVarint(b)
   353  			v, m := protowire.ConsumeBytes(b[n:])
   354  			md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i)
   355  			b = b[n+m:]
   356  		}
   357  	}
   358  	if numExtensions > 0 {
   359  		b := b0[posExtensions:]
   360  		for i := range md.L1.Extensions.List {
   361  			_, n := protowire.ConsumeVarint(b)
   362  			v, m := protowire.ConsumeBytes(b[n:])
   363  			md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i)
   364  			b = b[n+m:]
   365  		}
   366  	}
   367  }
   368  
   369  func (md *Message) unmarshalSeedOptions(b []byte) {
   370  	for len(b) > 0 {
   371  		num, typ, n := protowire.ConsumeTag(b)
   372  		b = b[n:]
   373  		switch typ {
   374  		case protowire.VarintType:
   375  			v, m := protowire.ConsumeVarint(b)
   376  			b = b[m:]
   377  			switch num {
   378  			case genid.MessageOptions_MapEntry_field_number:
   379  				md.L1.IsMapEntry = protowire.DecodeBool(v)
   380  			case genid.MessageOptions_MessageSetWireFormat_field_number:
   381  				md.L1.IsMessageSet = protowire.DecodeBool(v)
   382  			}
   383  		default:
   384  			m := protowire.ConsumeFieldValue(num, typ, b)
   385  			b = b[m:]
   386  		}
   387  	}
   388  }
   389  
   390  func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
   391  	xd.L0.ParentFile = pf
   392  	xd.L0.Parent = pd
   393  	xd.L0.Index = i
   394  
   395  	for len(b) > 0 {
   396  		num, typ, n := protowire.ConsumeTag(b)
   397  		b = b[n:]
   398  		switch typ {
   399  		case protowire.VarintType:
   400  			v, m := protowire.ConsumeVarint(b)
   401  			b = b[m:]
   402  			switch num {
   403  			case genid.FieldDescriptorProto_Number_field_number:
   404  				xd.L1.Number = protoreflect.FieldNumber(v)
   405  			case genid.FieldDescriptorProto_Label_field_number:
   406  				xd.L1.Cardinality = protoreflect.Cardinality(v)
   407  			case genid.FieldDescriptorProto_Type_field_number:
   408  				xd.L1.Kind = protoreflect.Kind(v)
   409  			}
   410  		case protowire.BytesType:
   411  			v, m := protowire.ConsumeBytes(b)
   412  			b = b[m:]
   413  			switch num {
   414  			case genid.FieldDescriptorProto_Name_field_number:
   415  				xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
   416  			case genid.FieldDescriptorProto_Extendee_field_number:
   417  				xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
   418  			}
   419  		default:
   420  			m := protowire.ConsumeFieldValue(num, typ, b)
   421  			b = b[m:]
   422  		}
   423  	}
   424  }
   425  
   426  func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protoreflect.Descriptor, i int) {
   427  	sd.L0.ParentFile = pf
   428  	sd.L0.Parent = pd
   429  	sd.L0.Index = i
   430  
   431  	for len(b) > 0 {
   432  		num, typ, n := protowire.ConsumeTag(b)
   433  		b = b[n:]
   434  		switch typ {
   435  		case protowire.BytesType:
   436  			v, m := protowire.ConsumeBytes(b)
   437  			b = b[m:]
   438  			switch num {
   439  			case genid.ServiceDescriptorProto_Name_field_number:
   440  				sd.L0.FullName = appendFullName(sb, pd.FullName(), v)
   441  			}
   442  		default:
   443  			m := protowire.ConsumeFieldValue(num, typ, b)
   444  			b = b[m:]
   445  		}
   446  	}
   447  }
   448  
   449  var nameBuilderPool = sync.Pool{
   450  	New: func() interface{} { return new(strs.Builder) },
   451  }
   452  
   453  func getBuilder() *strs.Builder {
   454  	return nameBuilderPool.Get().(*strs.Builder)
   455  }
   456  func putBuilder(b *strs.Builder) {
   457  	nameBuilderPool.Put(b)
   458  }
   459  
   460  // makeFullName converts b to a protoreflect.FullName,
   461  // where b must start with a leading dot.
   462  func makeFullName(sb *strs.Builder, b []byte) protoreflect.FullName {
   463  	if len(b) == 0 || b[0] != '.' {
   464  		panic("name reference must be fully qualified")
   465  	}
   466  	return protoreflect.FullName(sb.MakeString(b[1:]))
   467  }
   468  
   469  func appendFullName(sb *strs.Builder, prefix protoreflect.FullName, suffix []byte) protoreflect.FullName {
   470  	return sb.AppendFullName(prefix, protoreflect.Name(strs.UnsafeString(suffix)))
   471  }
   472  

View as plain text