1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2010 The Go Authors. All rights reserved. 4// https://github.com/golang/protobuf 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: 9// 10// * Redistributions of source code must retain the above copyright 11// notice, this list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above 13// copyright notice, this list of conditions and the following disclaimer 14// in the documentation and/or other materials provided with the 15// distribution. 16// * Neither the name of Google Inc. nor the names of its 17// contributors may be used to endorse or promote products derived from 18// this software without specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32package proto 33 34/* 35 * Routines for encoding data into the wire format for protocol buffers. 36 */ 37 38import ( 39 "fmt" 40 "log" 41 "os" 42 "reflect" 43 "sort" 44 "strconv" 45 "strings" 46 "sync" 47) 48 49const debug bool = false 50 51// Constants that identify the encoding of a value on the wire. 52const ( 53 WireVarint = 0 54 WireFixed64 = 1 55 WireBytes = 2 56 WireStartGroup = 3 57 WireEndGroup = 4 58 WireFixed32 = 5 59) 60 61const startSize = 10 // initial slice/string sizes 62 63// Encoders are defined in encode.go 64// An encoder outputs the full representation of a field, including its 65// tag and encoder type. 66type encoder func(p *Buffer, prop *Properties, base structPointer) error 67 68// A valueEncoder encodes a single integer in a particular encoding. 69type valueEncoder func(o *Buffer, x uint64) error 70 71// Sizers are defined in encode.go 72// A sizer returns the encoded size of a field, including its tag and encoder 73// type. 74type sizer func(prop *Properties, base structPointer) int 75 76// A valueSizer returns the encoded size of a single integer in a particular 77// encoding. 78type valueSizer func(x uint64) int 79 80// Decoders are defined in decode.go 81// A decoder creates a value from its wire representation. 82// Unrecognized subelements are saved in unrec. 83type decoder func(p *Buffer, prop *Properties, base structPointer) error 84 85// A valueDecoder decodes a single integer in a particular encoding. 86type valueDecoder func(o *Buffer) (x uint64, err error) 87 88// A oneofMarshaler does the marshaling for all oneof fields in a message. 89type oneofMarshaler func(Message, *Buffer) error 90 91// A oneofUnmarshaler does the unmarshaling for a oneof field in a message. 92type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error) 93 94// A oneofSizer does the sizing for all oneof fields in a message. 95type oneofSizer func(Message) int 96 97// tagMap is an optimization over map[int]int for typical protocol buffer 98// use-cases. Encoded protocol buffers are often in tag order with small tag 99// numbers. 100type tagMap struct { 101 fastTags []int 102 slowTags map[int]int 103} 104 105// tagMapFastLimit is the upper bound on the tag number that will be stored in 106// the tagMap slice rather than its map. 107const tagMapFastLimit = 1024 108 109func (p *tagMap) get(t int) (int, bool) { 110 if t > 0 && t < tagMapFastLimit { 111 if t >= len(p.fastTags) { 112 return 0, false 113 } 114 fi := p.fastTags[t] 115 return fi, fi >= 0 116 } 117 fi, ok := p.slowTags[t] 118 return fi, ok 119} 120 121func (p *tagMap) put(t int, fi int) { 122 if t > 0 && t < tagMapFastLimit { 123 for len(p.fastTags) < t+1 { 124 p.fastTags = append(p.fastTags, -1) 125 } 126 p.fastTags[t] = fi 127 return 128 } 129 if p.slowTags == nil { 130 p.slowTags = make(map[int]int) 131 } 132 p.slowTags[t] = fi 133} 134 135// StructProperties represents properties for all the fields of a struct. 136// decoderTags and decoderOrigNames should only be used by the decoder. 137type StructProperties struct { 138 Prop []*Properties // properties for each field 139 reqCount int // required count 140 decoderTags tagMap // map from proto tag to struct field number 141 decoderOrigNames map[string]int // map from original name to struct field number 142 order []int // list of struct field numbers in tag order 143 unrecField field // field id of the XXX_unrecognized []byte field 144 extendable bool // is this an extendable proto 145 146 oneofMarshaler oneofMarshaler 147 oneofUnmarshaler oneofUnmarshaler 148 oneofSizer oneofSizer 149 stype reflect.Type 150 151 // OneofTypes contains information about the oneof fields in this message. 152 // It is keyed by the original name of a field. 153 OneofTypes map[string]*OneofProperties 154} 155 156// OneofProperties represents information about a specific field in a oneof. 157type OneofProperties struct { 158 Type reflect.Type // pointer to generated struct type for this oneof field 159 Field int // struct field number of the containing oneof in the message 160 Prop *Properties 161} 162 163// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec. 164// See encode.go, (*Buffer).enc_struct. 165 166func (sp *StructProperties) Len() int { return len(sp.order) } 167func (sp *StructProperties) Less(i, j int) bool { 168 return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag 169} 170func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] } 171 172// Properties represents the protocol-specific behavior of a single struct field. 173type Properties struct { 174 Name string // name of the field, for error messages 175 OrigName string // original name before protocol compiler (always set) 176 JSONName string // name to use for JSON; determined by protoc 177 Wire string 178 WireType int 179 Tag int 180 Required bool 181 Optional bool 182 Repeated bool 183 Packed bool // relevant for repeated primitives only 184 Enum string // set for enum types only 185 proto3 bool // whether this is known to be a proto3 field; set for []byte only 186 oneof bool // whether this is a oneof field 187 188 Default string // default value 189 HasDefault bool // whether an explicit default was provided 190 def_uint64 uint64 191 192 enc encoder 193 valEnc valueEncoder // set for bool and numeric types only 194 field field 195 tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType) 196 tagbuf [8]byte 197 stype reflect.Type // set for struct types only 198 sprop *StructProperties // set for struct types only 199 isMarshaler bool 200 isUnmarshaler bool 201 202 mtype reflect.Type // set for map types only 203 mkeyprop *Properties // set for map types only 204 mvalprop *Properties // set for map types only 205 206 size sizer 207 valSize valueSizer // set for bool and numeric types only 208 209 dec decoder 210 valDec valueDecoder // set for bool and numeric types only 211 212 // If this is a packable field, this will be the decoder for the packed version of the field. 213 packedDec decoder 214} 215 216// String formats the properties in the protobuf struct field tag style. 217func (p *Properties) String() string { 218 s := p.Wire 219 s = "," 220 s += strconv.Itoa(p.Tag) 221 if p.Required { 222 s += ",req" 223 } 224 if p.Optional { 225 s += ",opt" 226 } 227 if p.Repeated { 228 s += ",rep" 229 } 230 if p.Packed { 231 s += ",packed" 232 } 233 s += ",name=" + p.OrigName 234 if p.JSONName != p.OrigName { 235 s += ",json=" + p.JSONName 236 } 237 if p.proto3 { 238 s += ",proto3" 239 } 240 if p.oneof { 241 s += ",oneof" 242 } 243 if len(p.Enum) > 0 { 244 s += ",enum=" + p.Enum 245 } 246 if p.HasDefault { 247 s += ",def=" + p.Default 248 } 249 return s 250} 251 252// Parse populates p by parsing a string in the protobuf struct field tag style. 253func (p *Properties) Parse(s string) { 254 // "bytes,49,opt,name=foo,def=hello!" 255 fields := strings.Split(s, ",") // breaks def=, but handled below. 256 if len(fields) < 2 { 257 fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) 258 return 259 } 260 261 p.Wire = fields[0] 262 switch p.Wire { 263 case "varint": 264 p.WireType = WireVarint 265 p.valEnc = (*Buffer).EncodeVarint 266 p.valDec = (*Buffer).DecodeVarint 267 p.valSize = sizeVarint 268 case "fixed32": 269 p.WireType = WireFixed32 270 p.valEnc = (*Buffer).EncodeFixed32 271 p.valDec = (*Buffer).DecodeFixed32 272 p.valSize = sizeFixed32 273 case "fixed64": 274 p.WireType = WireFixed64 275 p.valEnc = (*Buffer).EncodeFixed64 276 p.valDec = (*Buffer).DecodeFixed64 277 p.valSize = sizeFixed64 278 case "zigzag32": 279 p.WireType = WireVarint 280 p.valEnc = (*Buffer).EncodeZigzag32 281 p.valDec = (*Buffer).DecodeZigzag32 282 p.valSize = sizeZigzag32 283 case "zigzag64": 284 p.WireType = WireVarint 285 p.valEnc = (*Buffer).EncodeZigzag64 286 p.valDec = (*Buffer).DecodeZigzag64 287 p.valSize = sizeZigzag64 288 case "bytes", "group": 289 p.WireType = WireBytes 290 // no numeric converter for non-numeric types 291 default: 292 fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) 293 return 294 } 295 296 var err error 297 p.Tag, err = strconv.Atoi(fields[1]) 298 if err != nil { 299 return 300 } 301 302 for i := 2; i < len(fields); i++ { 303 f := fields[i] 304 switch { 305 case f == "req": 306 p.Required = true 307 case f == "opt": 308 p.Optional = true 309 case f == "rep": 310 p.Repeated = true 311 case f == "packed": 312 p.Packed = true 313 case strings.HasPrefix(f, "name="): 314 p.OrigName = f[5:] 315 case strings.HasPrefix(f, "json="): 316 p.JSONName = f[5:] 317 case strings.HasPrefix(f, "enum="): 318 p.Enum = f[5:] 319 case f == "proto3": 320 p.proto3 = true 321 case f == "oneof": 322 p.oneof = true 323 case strings.HasPrefix(f, "def="): 324 p.HasDefault = true 325 p.Default = f[4:] // rest of string 326 if i+1 < len(fields) { 327 // Commas aren't escaped, and def is always last. 328 p.Default += "," + strings.Join(fields[i+1:], ",") 329 break 330 } 331 } 332 } 333} 334 335func logNoSliceEnc(t1, t2 reflect.Type) { 336 fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2) 337} 338 339var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem() 340 341// Initialize the fields for encoding and decoding. 342func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) { 343 p.enc = nil 344 p.dec = nil 345 p.size = nil 346 347 switch t1 := typ; t1.Kind() { 348 default: 349 fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1) 350 351 // proto3 scalar types 352 353 case reflect.Bool: 354 p.enc = (*Buffer).enc_proto3_bool 355 p.dec = (*Buffer).dec_proto3_bool 356 p.size = size_proto3_bool 357 case reflect.Int32: 358 p.enc = (*Buffer).enc_proto3_int32 359 p.dec = (*Buffer).dec_proto3_int32 360 p.size = size_proto3_int32 361 case reflect.Uint32: 362 p.enc = (*Buffer).enc_proto3_uint32 363 p.dec = (*Buffer).dec_proto3_int32 // can reuse 364 p.size = size_proto3_uint32 365 case reflect.Int64, reflect.Uint64: 366 p.enc = (*Buffer).enc_proto3_int64 367 p.dec = (*Buffer).dec_proto3_int64 368 p.size = size_proto3_int64 369 case reflect.Float32: 370 p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits 371 p.dec = (*Buffer).dec_proto3_int32 372 p.size = size_proto3_uint32 373 case reflect.Float64: 374 p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits 375 p.dec = (*Buffer).dec_proto3_int64 376 p.size = size_proto3_int64 377 case reflect.String: 378 p.enc = (*Buffer).enc_proto3_string 379 p.dec = (*Buffer).dec_proto3_string 380 p.size = size_proto3_string 381 382 case reflect.Ptr: 383 switch t2 := t1.Elem(); t2.Kind() { 384 default: 385 fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2) 386 break 387 case reflect.Bool: 388 p.enc = (*Buffer).enc_bool 389 p.dec = (*Buffer).dec_bool 390 p.size = size_bool 391 case reflect.Int32: 392 p.enc = (*Buffer).enc_int32 393 p.dec = (*Buffer).dec_int32 394 p.size = size_int32 395 case reflect.Uint32: 396 p.enc = (*Buffer).enc_uint32 397 p.dec = (*Buffer).dec_int32 // can reuse 398 p.size = size_uint32 399 case reflect.Int64, reflect.Uint64: 400 p.enc = (*Buffer).enc_int64 401 p.dec = (*Buffer).dec_int64 402 p.size = size_int64 403 case reflect.Float32: 404 p.enc = (*Buffer).enc_uint32 // can just treat them as bits 405 p.dec = (*Buffer).dec_int32 406 p.size = size_uint32 407 case reflect.Float64: 408 p.enc = (*Buffer).enc_int64 // can just treat them as bits 409 p.dec = (*Buffer).dec_int64 410 p.size = size_int64 411 case reflect.String: 412 p.enc = (*Buffer).enc_string 413 p.dec = (*Buffer).dec_string 414 p.size = size_string 415 case reflect.Struct: 416 p.stype = t1.Elem() 417 p.isMarshaler = isMarshaler(t1) 418 p.isUnmarshaler = isUnmarshaler(t1) 419 if p.Wire == "bytes" { 420 p.enc = (*Buffer).enc_struct_message 421 p.dec = (*Buffer).dec_struct_message 422 p.size = size_struct_message 423 } else { 424 p.enc = (*Buffer).enc_struct_group 425 p.dec = (*Buffer).dec_struct_group 426 p.size = size_struct_group 427 } 428 } 429 430 case reflect.Slice: 431 switch t2 := t1.Elem(); t2.Kind() { 432 default: 433 logNoSliceEnc(t1, t2) 434 break 435 case reflect.Bool: 436 if p.Packed { 437 p.enc = (*Buffer).enc_slice_packed_bool 438 p.size = size_slice_packed_bool 439 } else { 440 p.enc = (*Buffer).enc_slice_bool 441 p.size = size_slice_bool 442 } 443 p.dec = (*Buffer).dec_slice_bool 444 p.packedDec = (*Buffer).dec_slice_packed_bool 445 case reflect.Int32: 446 if p.Packed { 447 p.enc = (*Buffer).enc_slice_packed_int32 448 p.size = size_slice_packed_int32 449 } else { 450 p.enc = (*Buffer).enc_slice_int32 451 p.size = size_slice_int32 452 } 453 p.dec = (*Buffer).dec_slice_int32 454 p.packedDec = (*Buffer).dec_slice_packed_int32 455 case reflect.Uint32: 456 if p.Packed { 457 p.enc = (*Buffer).enc_slice_packed_uint32 458 p.size = size_slice_packed_uint32 459 } else { 460 p.enc = (*Buffer).enc_slice_uint32 461 p.size = size_slice_uint32 462 } 463 p.dec = (*Buffer).dec_slice_int32 464 p.packedDec = (*Buffer).dec_slice_packed_int32 465 case reflect.Int64, reflect.Uint64: 466 if p.Packed { 467 p.enc = (*Buffer).enc_slice_packed_int64 468 p.size = size_slice_packed_int64 469 } else { 470 p.enc = (*Buffer).enc_slice_int64 471 p.size = size_slice_int64 472 } 473 p.dec = (*Buffer).dec_slice_int64 474 p.packedDec = (*Buffer).dec_slice_packed_int64 475 case reflect.Uint8: 476 p.dec = (*Buffer).dec_slice_byte 477 if p.proto3 { 478 p.enc = (*Buffer).enc_proto3_slice_byte 479 p.size = size_proto3_slice_byte 480 } else { 481 p.enc = (*Buffer).enc_slice_byte 482 p.size = size_slice_byte 483 } 484 case reflect.Float32, reflect.Float64: 485 switch t2.Bits() { 486 case 32: 487 // can just treat them as bits 488 if p.Packed { 489 p.enc = (*Buffer).enc_slice_packed_uint32 490 p.size = size_slice_packed_uint32 491 } else { 492 p.enc = (*Buffer).enc_slice_uint32 493 p.size = size_slice_uint32 494 } 495 p.dec = (*Buffer).dec_slice_int32 496 p.packedDec = (*Buffer).dec_slice_packed_int32 497 case 64: 498 // can just treat them as bits 499 if p.Packed { 500 p.enc = (*Buffer).enc_slice_packed_int64 501 p.size = size_slice_packed_int64 502 } else { 503 p.enc = (*Buffer).enc_slice_int64 504 p.size = size_slice_int64 505 } 506 p.dec = (*Buffer).dec_slice_int64 507 p.packedDec = (*Buffer).dec_slice_packed_int64 508 default: 509 logNoSliceEnc(t1, t2) 510 break 511 } 512 case reflect.String: 513 p.enc = (*Buffer).enc_slice_string 514 p.dec = (*Buffer).dec_slice_string 515 p.size = size_slice_string 516 case reflect.Ptr: 517 switch t3 := t2.Elem(); t3.Kind() { 518 default: 519 fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3) 520 break 521 case reflect.Struct: 522 p.stype = t2.Elem() 523 p.isMarshaler = isMarshaler(t2) 524 p.isUnmarshaler = isUnmarshaler(t2) 525 if p.Wire == "bytes" { 526 p.enc = (*Buffer).enc_slice_struct_message 527 p.dec = (*Buffer).dec_slice_struct_message 528 p.size = size_slice_struct_message 529 } else { 530 p.enc = (*Buffer).enc_slice_struct_group 531 p.dec = (*Buffer).dec_slice_struct_group 532 p.size = size_slice_struct_group 533 } 534 } 535 case reflect.Slice: 536 switch t2.Elem().Kind() { 537 default: 538 fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem()) 539 break 540 case reflect.Uint8: 541 p.enc = (*Buffer).enc_slice_slice_byte 542 p.dec = (*Buffer).dec_slice_slice_byte 543 p.size = size_slice_slice_byte 544 } 545 } 546 547 case reflect.Map: 548 p.enc = (*Buffer).enc_new_map 549 p.dec = (*Buffer).dec_new_map 550 p.size = size_new_map 551 552 p.mtype = t1 553 p.mkeyprop = &Properties{} 554 p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) 555 p.mvalprop = &Properties{} 556 vtype := p.mtype.Elem() 557 if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { 558 // The value type is not a message (*T) or bytes ([]byte), 559 // so we need encoders for the pointer to this type. 560 vtype = reflect.PtrTo(vtype) 561 } 562 p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) 563 } 564 565 // precalculate tag code 566 wire := p.WireType 567 if p.Packed { 568 wire = WireBytes 569 } 570 x := uint32(p.Tag)<<3 | uint32(wire) 571 i := 0 572 for i = 0; x > 127; i++ { 573 p.tagbuf[i] = 0x80 | uint8(x&0x7F) 574 x >>= 7 575 } 576 p.tagbuf[i] = uint8(x) 577 p.tagcode = p.tagbuf[0 : i+1] 578 579 if p.stype != nil { 580 if lockGetProp { 581 p.sprop = GetProperties(p.stype) 582 } else { 583 p.sprop = getPropertiesLocked(p.stype) 584 } 585 } 586} 587 588var ( 589 marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() 590 unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() 591) 592 593// isMarshaler reports whether type t implements Marshaler. 594func isMarshaler(t reflect.Type) bool { 595 // We're checking for (likely) pointer-receiver methods 596 // so if t is not a pointer, something is very wrong. 597 // The calls above only invoke isMarshaler on pointer types. 598 if t.Kind() != reflect.Ptr { 599 panic("proto: misuse of isMarshaler") 600 } 601 return t.Implements(marshalerType) 602} 603 604// isUnmarshaler reports whether type t implements Unmarshaler. 605func isUnmarshaler(t reflect.Type) bool { 606 // We're checking for (likely) pointer-receiver methods 607 // so if t is not a pointer, something is very wrong. 608 // The calls above only invoke isUnmarshaler on pointer types. 609 if t.Kind() != reflect.Ptr { 610 panic("proto: misuse of isUnmarshaler") 611 } 612 return t.Implements(unmarshalerType) 613} 614 615// Init populates the properties from a protocol buffer struct tag. 616func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) { 617 p.init(typ, name, tag, f, true) 618} 619 620func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) { 621 // "bytes,49,opt,def=hello!" 622 p.Name = name 623 p.OrigName = name 624 if f != nil { 625 p.field = toField(f) 626 } 627 if tag == "" { 628 return 629 } 630 p.Parse(tag) 631 p.setEncAndDec(typ, f, lockGetProp) 632} 633 634var ( 635 propertiesMu sync.RWMutex 636 propertiesMap = make(map[reflect.Type]*StructProperties) 637) 638 639// GetProperties returns the list of properties for the type represented by t. 640// t must represent a generated struct type of a protocol message. 641func GetProperties(t reflect.Type) *StructProperties { 642 if t.Kind() != reflect.Struct { 643 panic("proto: type must have kind struct") 644 } 645 646 // Most calls to GetProperties in a long-running program will be 647 // retrieving details for types we have seen before. 648 propertiesMu.RLock() 649 sprop, ok := propertiesMap[t] 650 propertiesMu.RUnlock() 651 if ok { 652 if collectStats { 653 stats.Chit++ 654 } 655 return sprop 656 } 657 658 propertiesMu.Lock() 659 sprop = getPropertiesLocked(t) 660 propertiesMu.Unlock() 661 return sprop 662} 663 664// getPropertiesLocked requires that propertiesMu is held. 665func getPropertiesLocked(t reflect.Type) *StructProperties { 666 if prop, ok := propertiesMap[t]; ok { 667 if collectStats { 668 stats.Chit++ 669 } 670 return prop 671 } 672 if collectStats { 673 stats.Cmiss++ 674 } 675 676 prop := new(StructProperties) 677 // in case of recursive protos, fill this in now. 678 propertiesMap[t] = prop 679 680 // build properties 681 prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) || 682 reflect.PtrTo(t).Implements(extendableProtoV1Type) 683 prop.unrecField = invalidField 684 prop.Prop = make([]*Properties, t.NumField()) 685 prop.order = make([]int, t.NumField()) 686 687 for i := 0; i < t.NumField(); i++ { 688 f := t.Field(i) 689 p := new(Properties) 690 name := f.Name 691 p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false) 692 693 if f.Name == "XXX_InternalExtensions" { // special case 694 p.enc = (*Buffer).enc_exts 695 p.dec = nil // not needed 696 p.size = size_exts 697 } else if f.Name == "XXX_extensions" { // special case 698 p.enc = (*Buffer).enc_map 699 p.dec = nil // not needed 700 p.size = size_map 701 } else if f.Name == "XXX_unrecognized" { // special case 702 prop.unrecField = toField(&f) 703 } 704 oneof := f.Tag.Get("protobuf_oneof") // special case 705 if oneof != "" { 706 // Oneof fields don't use the traditional protobuf tag. 707 p.OrigName = oneof 708 } 709 prop.Prop[i] = p 710 prop.order[i] = i 711 if debug { 712 print(i, " ", f.Name, " ", t.String(), " ") 713 if p.Tag > 0 { 714 print(p.String()) 715 } 716 print("\n") 717 } 718 if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" { 719 fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]") 720 } 721 } 722 723 // Re-order prop.order. 724 sort.Sort(prop) 725 726 type oneofMessage interface { 727 XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) 728 } 729 if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { 730 var oots []interface{} 731 prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs() 732 prop.stype = t 733 734 // Interpret oneof metadata. 735 prop.OneofTypes = make(map[string]*OneofProperties) 736 for _, oot := range oots { 737 oop := &OneofProperties{ 738 Type: reflect.ValueOf(oot).Type(), // *T 739 Prop: new(Properties), 740 } 741 sft := oop.Type.Elem().Field(0) 742 oop.Prop.Name = sft.Name 743 oop.Prop.Parse(sft.Tag.Get("protobuf")) 744 // There will be exactly one interface field that 745 // this new value is assignable to. 746 for i := 0; i < t.NumField(); i++ { 747 f := t.Field(i) 748 if f.Type.Kind() != reflect.Interface { 749 continue 750 } 751 if !oop.Type.AssignableTo(f.Type) { 752 continue 753 } 754 oop.Field = i 755 break 756 } 757 prop.OneofTypes[oop.Prop.OrigName] = oop 758 } 759 } 760 761 // build required counts 762 // build tags 763 reqCount := 0 764 prop.decoderOrigNames = make(map[string]int) 765 for i, p := range prop.Prop { 766 if strings.HasPrefix(p.Name, "XXX_") { 767 // Internal fields should not appear in tags/origNames maps. 768 // They are handled specially when encoding and decoding. 769 continue 770 } 771 if p.Required { 772 reqCount++ 773 } 774 prop.decoderTags.put(p.Tag, i) 775 prop.decoderOrigNames[p.OrigName] = i 776 } 777 prop.reqCount = reqCount 778 779 return prop 780} 781 782// Return the Properties object for the x[0]'th field of the structure. 783func propByIndex(t reflect.Type, x []int) *Properties { 784 if len(x) != 1 { 785 fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t) 786 return nil 787 } 788 prop := GetProperties(t) 789 return prop.Prop[x[0]] 790} 791 792// Get the address and type of a pointer to a struct from an interface. 793func getbase(pb Message) (t reflect.Type, b structPointer, err error) { 794 if pb == nil { 795 err = ErrNil 796 return 797 } 798 // get the reflect type of the pointer to the struct. 799 t = reflect.TypeOf(pb) 800 // get the address of the struct. 801 value := reflect.ValueOf(pb) 802 b = toStructPointer(value) 803 return 804} 805 806// A global registry of enum types. 807// The generated code will register the generated maps by calling RegisterEnum. 808 809var enumValueMaps = make(map[string]map[string]int32) 810 811// RegisterEnum is called from the generated code to install the enum descriptor 812// maps into the global table to aid parsing text format protocol buffers. 813func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) { 814 if _, ok := enumValueMaps[typeName]; ok { 815 panic("proto: duplicate enum registered: " + typeName) 816 } 817 enumValueMaps[typeName] = valueMap 818} 819 820// EnumValueMap returns the mapping from names to integers of the 821// enum type enumType, or a nil if not found. 822func EnumValueMap(enumType string) map[string]int32 { 823 return enumValueMaps[enumType] 824} 825 826// A registry of all linked message types. 827// The string is a fully-qualified proto name ("pkg.Message"). 828var ( 829 protoTypes = make(map[string]reflect.Type) 830 revProtoTypes = make(map[reflect.Type]string) 831) 832 833// RegisterType is called from generated code and maps from the fully qualified 834// proto name to the type (pointer to struct) of the protocol buffer. 835func RegisterType(x Message, name string) { 836 if _, ok := protoTypes[name]; ok { 837 // TODO: Some day, make this a panic. 838 log.Printf("proto: duplicate proto type registered: %s", name) 839 return 840 } 841 t := reflect.TypeOf(x) 842 protoTypes[name] = t 843 revProtoTypes[t] = name 844} 845 846// MessageName returns the fully-qualified proto name for the given message type. 847func MessageName(x Message) string { 848 type xname interface { 849 XXX_MessageName() string 850 } 851 if m, ok := x.(xname); ok { 852 return m.XXX_MessageName() 853 } 854 return revProtoTypes[reflect.TypeOf(x)] 855} 856 857// MessageType returns the message type (pointer to struct) for a named message. 858func MessageType(name string) reflect.Type { return protoTypes[name] } 859 860// A registry of all linked proto files. 861var ( 862 protoFiles = make(map[string][]byte) // file name => fileDescriptor 863) 864 865// RegisterFile is called from generated code and maps from the 866// full file name of a .proto file to its compressed FileDescriptorProto. 867func RegisterFile(filename string, fileDescriptor []byte) { 868 protoFiles[filename] = fileDescriptor 869} 870 871// FileDescriptor returns the compressed FileDescriptorProto for a .proto file. 872func FileDescriptor(filename string) []byte { return protoFiles[filename] } 873