desc_init.go (13508B)
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 }