github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/encoding/gob/type.go (about) 1 // Copyright 2009 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 gob 6 7 import ( 8 "encoding" 9 "errors" 10 "fmt" 11 "os" 12 "reflect" 13 "sync" 14 "sync/atomic" 15 "unicode" 16 "unicode/utf8" 17 ) 18 19 // userTypeInfo stores the information associated with a type the user has handed 20 // to the package. It's computed once and stored in a map keyed by reflection 21 // type. 22 type userTypeInfo struct { 23 user reflect.Type // the type the user handed us 24 base reflect.Type // the base type after all indirections 25 indir int // number of indirections to reach the base type 26 externalEnc int // xGob, xBinary, or xText 27 externalDec int // xGob, xBinary, or xText 28 encIndir int8 // number of indirections to reach the receiver type; may be negative 29 decIndir int8 // number of indirections to reach the receiver type; may be negative 30 } 31 32 // externalEncoding bits 33 const ( 34 xGob = 1 + iota // GobEncoder or GobDecoder 35 xBinary // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler 36 xText // encoding.TextMarshaler or encoding.TextUnmarshaler 37 ) 38 39 var userTypeCache sync.Map // map[reflect.Type]*userTypeInfo 40 41 // validUserType returns, and saves, the information associated with user-provided type rt. 42 // If the user type is not valid, err will be non-nil. To be used when the error handler 43 // is not set up. 44 func validUserType(rt reflect.Type) (*userTypeInfo, error) { 45 if ui, ok := userTypeCache.Load(rt); ok { 46 return ui.(*userTypeInfo), nil 47 } 48 49 // Construct a new userTypeInfo and atomically add it to the userTypeCache. 50 // If we lose the race, we'll waste a little CPU and create a little garbage 51 // but return the existing value anyway. 52 53 ut := new(userTypeInfo) 54 ut.base = rt 55 ut.user = rt 56 // A type that is just a cycle of pointers (such as type T *T) cannot 57 // be represented in gobs, which need some concrete data. We use a 58 // cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6, 59 // pp 539-540. As we step through indirections, run another type at 60 // half speed. If they meet up, there's a cycle. 61 slowpoke := ut.base // walks half as fast as ut.base 62 for { 63 pt := ut.base 64 if pt.Kind() != reflect.Pointer { 65 break 66 } 67 ut.base = pt.Elem() 68 if ut.base == slowpoke { // ut.base lapped slowpoke 69 // recursive pointer type. 70 return nil, errors.New("can't represent recursive pointer type " + ut.base.String()) 71 } 72 if ut.indir%2 == 0 { 73 slowpoke = slowpoke.Elem() 74 } 75 ut.indir++ 76 } 77 78 if ok, indir := implementsInterface(ut.user, gobEncoderInterfaceType); ok { 79 ut.externalEnc, ut.encIndir = xGob, indir 80 } else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok { 81 ut.externalEnc, ut.encIndir = xBinary, indir 82 } 83 84 // NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility 85 // with older encodings for net.IP. See golang.org/issue/6760. 86 // } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok { 87 // ut.externalEnc, ut.encIndir = xText, indir 88 // } 89 90 if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok { 91 ut.externalDec, ut.decIndir = xGob, indir 92 } else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok { 93 ut.externalDec, ut.decIndir = xBinary, indir 94 } 95 96 // See note above. 97 // } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok { 98 // ut.externalDec, ut.decIndir = xText, indir 99 // } 100 101 ui, _ := userTypeCache.LoadOrStore(rt, ut) 102 return ui.(*userTypeInfo), nil 103 } 104 105 var ( 106 gobEncoderInterfaceType = reflect.TypeFor[GobEncoder]() 107 gobDecoderInterfaceType = reflect.TypeFor[GobDecoder]() 108 binaryMarshalerInterfaceType = reflect.TypeFor[encoding.BinaryMarshaler]() 109 binaryUnmarshalerInterfaceType = reflect.TypeFor[encoding.BinaryUnmarshaler]() 110 textMarshalerInterfaceType = reflect.TypeFor[encoding.TextMarshaler]() 111 textUnmarshalerInterfaceType = reflect.TypeFor[encoding.TextUnmarshaler]() 112 113 wireTypeType = reflect.TypeFor[wireType]() 114 ) 115 116 // implementsInterface reports whether the type implements the 117 // gobEncoder/gobDecoder interface. 118 // It also returns the number of indirections required to get to the 119 // implementation. 120 func implementsInterface(typ, gobEncDecType reflect.Type) (success bool, indir int8) { 121 if typ == nil { 122 return 123 } 124 rt := typ 125 // The type might be a pointer and we need to keep 126 // dereferencing to the base type until we find an implementation. 127 for { 128 if rt.Implements(gobEncDecType) { 129 return true, indir 130 } 131 if p := rt; p.Kind() == reflect.Pointer { 132 indir++ 133 if indir > 100 { // insane number of indirections 134 return false, 0 135 } 136 rt = p.Elem() 137 continue 138 } 139 break 140 } 141 // No luck yet, but if this is a base type (non-pointer), the pointer might satisfy. 142 if typ.Kind() != reflect.Pointer { 143 // Not a pointer, but does the pointer work? 144 if reflect.PointerTo(typ).Implements(gobEncDecType) { 145 return true, -1 146 } 147 } 148 return false, 0 149 } 150 151 // userType returns, and saves, the information associated with user-provided type rt. 152 // If the user type is not valid, it calls error. 153 func userType(rt reflect.Type) *userTypeInfo { 154 ut, err := validUserType(rt) 155 if err != nil { 156 error_(err) 157 } 158 return ut 159 } 160 161 // A typeId represents a gob Type as an integer that can be passed on the wire. 162 // Internally, typeIds are used as keys to a map to recover the underlying type info. 163 type typeId int32 164 165 var typeLock sync.Mutex // set while building a type 166 const firstUserId = 64 // lowest id number granted to user 167 168 type gobType interface { 169 id() typeId 170 setId(id typeId) 171 name() string 172 string() string // not public; only for debugging 173 safeString(seen map[typeId]bool) string 174 } 175 176 var ( 177 types = make(map[reflect.Type]gobType, 32) 178 idToTypeSlice = make([]gobType, 1, firstUserId) 179 builtinIdToTypeSlice [firstUserId]gobType // set in init() after builtins are established 180 ) 181 182 func idToType(id typeId) gobType { 183 if id < 0 || int(id) >= len(idToTypeSlice) { 184 return nil 185 } 186 return idToTypeSlice[id] 187 } 188 189 func builtinIdToType(id typeId) gobType { 190 if id < 0 || int(id) >= len(builtinIdToTypeSlice) { 191 return nil 192 } 193 return builtinIdToTypeSlice[id] 194 } 195 196 func setTypeId(typ gobType) { 197 // When building recursive types, someone may get there before us. 198 if typ.id() != 0 { 199 return 200 } 201 nextId := typeId(len(idToTypeSlice)) 202 typ.setId(nextId) 203 idToTypeSlice = append(idToTypeSlice, typ) 204 } 205 206 func (t typeId) gobType() gobType { 207 if t == 0 { 208 return nil 209 } 210 return idToType(t) 211 } 212 213 // string returns the string representation of the type associated with the typeId. 214 func (t typeId) string() string { 215 if t.gobType() == nil { 216 return "<nil>" 217 } 218 return t.gobType().string() 219 } 220 221 // Name returns the name of the type associated with the typeId. 222 func (t typeId) name() string { 223 if t.gobType() == nil { 224 return "<nil>" 225 } 226 return t.gobType().name() 227 } 228 229 // CommonType holds elements of all types. 230 // It is a historical artifact, kept for binary compatibility and exported 231 // only for the benefit of the package's encoding of type descriptors. It is 232 // not intended for direct use by clients. 233 type CommonType struct { 234 Name string 235 Id typeId 236 } 237 238 func (t *CommonType) id() typeId { return t.Id } 239 240 func (t *CommonType) setId(id typeId) { t.Id = id } 241 242 func (t *CommonType) string() string { return t.Name } 243 244 func (t *CommonType) safeString(seen map[typeId]bool) string { 245 return t.Name 246 } 247 248 func (t *CommonType) name() string { return t.Name } 249 250 // Create and check predefined types 251 // The string for tBytes is "bytes" not "[]byte" to signify its specialness. 252 253 var ( 254 // Primordial types, needed during initialization. 255 // Always passed as pointers so the interface{} type 256 // goes through without losing its interfaceness. 257 tBool = bootstrapType("bool", (*bool)(nil)) 258 tInt = bootstrapType("int", (*int)(nil)) 259 tUint = bootstrapType("uint", (*uint)(nil)) 260 tFloat = bootstrapType("float", (*float64)(nil)) 261 tBytes = bootstrapType("bytes", (*[]byte)(nil)) 262 tString = bootstrapType("string", (*string)(nil)) 263 tComplex = bootstrapType("complex", (*complex128)(nil)) 264 tInterface = bootstrapType("interface", (*any)(nil)) 265 // Reserve some Ids for compatible expansion 266 tReserved7 = bootstrapType("_reserved1", (*struct{ r7 int })(nil)) 267 tReserved6 = bootstrapType("_reserved1", (*struct{ r6 int })(nil)) 268 tReserved5 = bootstrapType("_reserved1", (*struct{ r5 int })(nil)) 269 tReserved4 = bootstrapType("_reserved1", (*struct{ r4 int })(nil)) 270 tReserved3 = bootstrapType("_reserved1", (*struct{ r3 int })(nil)) 271 tReserved2 = bootstrapType("_reserved1", (*struct{ r2 int })(nil)) 272 tReserved1 = bootstrapType("_reserved1", (*struct{ r1 int })(nil)) 273 ) 274 275 // Predefined because it's needed by the Decoder 276 var tWireType = mustGetTypeInfo(wireTypeType).id 277 var wireTypeUserInfo *userTypeInfo // userTypeInfo of wireType 278 279 func init() { 280 // Some magic numbers to make sure there are no surprises. 281 checkId(16, tWireType) 282 checkId(17, mustGetTypeInfo(reflect.TypeFor[arrayType]()).id) 283 checkId(18, mustGetTypeInfo(reflect.TypeFor[CommonType]()).id) 284 checkId(19, mustGetTypeInfo(reflect.TypeFor[sliceType]()).id) 285 checkId(20, mustGetTypeInfo(reflect.TypeFor[structType]()).id) 286 checkId(21, mustGetTypeInfo(reflect.TypeFor[fieldType]()).id) 287 checkId(23, mustGetTypeInfo(reflect.TypeFor[mapType]()).id) 288 289 copy(builtinIdToTypeSlice[:], idToTypeSlice) 290 291 // Move the id space upwards to allow for growth in the predefined world 292 // without breaking existing files. 293 if nextId := len(idToTypeSlice); nextId > firstUserId { 294 panic(fmt.Sprintln("nextId too large:", nextId)) 295 } 296 idToTypeSlice = idToTypeSlice[:firstUserId] 297 registerBasics() 298 wireTypeUserInfo = userType(wireTypeType) 299 } 300 301 // Array type 302 type arrayType struct { 303 CommonType 304 Elem typeId 305 Len int 306 } 307 308 func newArrayType(name string) *arrayType { 309 a := &arrayType{CommonType{Name: name}, 0, 0} 310 return a 311 } 312 313 func (a *arrayType) init(elem gobType, len int) { 314 // Set our type id before evaluating the element's, in case it's our own. 315 setTypeId(a) 316 a.Elem = elem.id() 317 a.Len = len 318 } 319 320 func (a *arrayType) safeString(seen map[typeId]bool) string { 321 if seen[a.Id] { 322 return a.Name 323 } 324 seen[a.Id] = true 325 return fmt.Sprintf("[%d]%s", a.Len, a.Elem.gobType().safeString(seen)) 326 } 327 328 func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } 329 330 // GobEncoder type (something that implements the GobEncoder interface) 331 type gobEncoderType struct { 332 CommonType 333 } 334 335 func newGobEncoderType(name string) *gobEncoderType { 336 g := &gobEncoderType{CommonType{Name: name}} 337 setTypeId(g) 338 return g 339 } 340 341 func (g *gobEncoderType) safeString(seen map[typeId]bool) string { 342 return g.Name 343 } 344 345 func (g *gobEncoderType) string() string { return g.Name } 346 347 // Map type 348 type mapType struct { 349 CommonType 350 Key typeId 351 Elem typeId 352 } 353 354 func newMapType(name string) *mapType { 355 m := &mapType{CommonType{Name: name}, 0, 0} 356 return m 357 } 358 359 func (m *mapType) init(key, elem gobType) { 360 // Set our type id before evaluating the element's, in case it's our own. 361 setTypeId(m) 362 m.Key = key.id() 363 m.Elem = elem.id() 364 } 365 366 func (m *mapType) safeString(seen map[typeId]bool) string { 367 if seen[m.Id] { 368 return m.Name 369 } 370 seen[m.Id] = true 371 key := m.Key.gobType().safeString(seen) 372 elem := m.Elem.gobType().safeString(seen) 373 return fmt.Sprintf("map[%s]%s", key, elem) 374 } 375 376 func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } 377 378 // Slice type 379 type sliceType struct { 380 CommonType 381 Elem typeId 382 } 383 384 func newSliceType(name string) *sliceType { 385 s := &sliceType{CommonType{Name: name}, 0} 386 return s 387 } 388 389 func (s *sliceType) init(elem gobType) { 390 // Set our type id before evaluating the element's, in case it's our own. 391 setTypeId(s) 392 // See the comments about ids in newTypeObject. Only slices and 393 // structs have mutual recursion. 394 if elem.id() == 0 { 395 setTypeId(elem) 396 } 397 s.Elem = elem.id() 398 } 399 400 func (s *sliceType) safeString(seen map[typeId]bool) string { 401 if seen[s.Id] { 402 return s.Name 403 } 404 seen[s.Id] = true 405 return fmt.Sprintf("[]%s", s.Elem.gobType().safeString(seen)) 406 } 407 408 func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } 409 410 // Struct type 411 type fieldType struct { 412 Name string 413 Id typeId 414 } 415 416 type structType struct { 417 CommonType 418 Field []fieldType 419 } 420 421 func (s *structType) safeString(seen map[typeId]bool) string { 422 if s == nil { 423 return "<nil>" 424 } 425 if _, ok := seen[s.Id]; ok { 426 return s.Name 427 } 428 seen[s.Id] = true 429 str := s.Name + " = struct { " 430 for _, f := range s.Field { 431 str += fmt.Sprintf("%s %s; ", f.Name, f.Id.gobType().safeString(seen)) 432 } 433 str += "}" 434 return str 435 } 436 437 func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } 438 439 func newStructType(name string) *structType { 440 s := &structType{CommonType{Name: name}, nil} 441 // For historical reasons we set the id here rather than init. 442 // See the comment in newTypeObject for details. 443 setTypeId(s) 444 return s 445 } 446 447 // newTypeObject allocates a gobType for the reflection type rt. 448 // Unless ut represents a GobEncoder, rt should be the base type 449 // of ut. 450 // This is only called from the encoding side. The decoding side 451 // works through typeIds and userTypeInfos alone. 452 func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { 453 // Does this type implement GobEncoder? 454 if ut.externalEnc != 0 { 455 return newGobEncoderType(name), nil 456 } 457 var err error 458 var type0, type1 gobType 459 defer func() { 460 if err != nil { 461 delete(types, rt) 462 } 463 }() 464 // Install the top-level type before the subtypes (e.g. struct before 465 // fields) so recursive types can be constructed safely. 466 switch t := rt; t.Kind() { 467 // All basic types are easy: they are predefined. 468 case reflect.Bool: 469 return tBool.gobType(), nil 470 471 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 472 return tInt.gobType(), nil 473 474 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 475 return tUint.gobType(), nil 476 477 case reflect.Float32, reflect.Float64: 478 return tFloat.gobType(), nil 479 480 case reflect.Complex64, reflect.Complex128: 481 return tComplex.gobType(), nil 482 483 case reflect.String: 484 return tString.gobType(), nil 485 486 case reflect.Interface: 487 return tInterface.gobType(), nil 488 489 case reflect.Array: 490 at := newArrayType(name) 491 types[rt] = at 492 type0, err = getBaseType("", t.Elem()) 493 if err != nil { 494 return nil, err 495 } 496 // Historical aside: 497 // For arrays, maps, and slices, we set the type id after the elements 498 // are constructed. This is to retain the order of type id allocation after 499 // a fix made to handle recursive types, which changed the order in 500 // which types are built. Delaying the setting in this way preserves 501 // type ids while allowing recursive types to be described. Structs, 502 // done below, were already handling recursion correctly so they 503 // assign the top-level id before those of the field. 504 at.init(type0, t.Len()) 505 return at, nil 506 507 case reflect.Map: 508 mt := newMapType(name) 509 types[rt] = mt 510 type0, err = getBaseType("", t.Key()) 511 if err != nil { 512 return nil, err 513 } 514 type1, err = getBaseType("", t.Elem()) 515 if err != nil { 516 return nil, err 517 } 518 mt.init(type0, type1) 519 return mt, nil 520 521 case reflect.Slice: 522 // []byte == []uint8 is a special case 523 if t.Elem().Kind() == reflect.Uint8 { 524 return tBytes.gobType(), nil 525 } 526 st := newSliceType(name) 527 types[rt] = st 528 type0, err = getBaseType(t.Elem().Name(), t.Elem()) 529 if err != nil { 530 return nil, err 531 } 532 st.init(type0) 533 return st, nil 534 535 case reflect.Struct: 536 st := newStructType(name) 537 types[rt] = st 538 idToTypeSlice[st.id()] = st 539 for i := 0; i < t.NumField(); i++ { 540 f := t.Field(i) 541 if !isSent(t, &f) { 542 continue 543 } 544 typ := userType(f.Type).base 545 tname := typ.Name() 546 if tname == "" { 547 t := userType(f.Type).base 548 tname = t.String() 549 } 550 gt, err := getBaseType(tname, f.Type) 551 if err != nil { 552 return nil, err 553 } 554 // Some mutually recursive types can cause us to be here while 555 // still defining the element. Fix the element type id here. 556 // We could do this more neatly by setting the id at the start of 557 // building every type, but that would break binary compatibility. 558 if gt.id() == 0 { 559 setTypeId(gt) 560 } 561 st.Field = append(st.Field, fieldType{f.Name, gt.id()}) 562 } 563 return st, nil 564 565 default: 566 return nil, errors.New("gob NewTypeObject can't handle type: " + rt.String()) 567 } 568 } 569 570 // isExported reports whether this is an exported - upper case - name. 571 func isExported(name string) bool { 572 rune, _ := utf8.DecodeRuneInString(name) 573 return unicode.IsUpper(rune) 574 } 575 576 // isSent reports whether this struct field is to be transmitted. 577 // It will be transmitted only if it is exported and not a chan or func field 578 // or pointer to chan or func. 579 func isSent(struct_ reflect.Type, field *reflect.StructField) bool { 580 if !isExported(field.Name) { 581 return false 582 } 583 // If the field is a chan or func or pointer thereto, don't send it. 584 // That is, treat it like an unexported field. 585 typ := field.Type 586 for typ.Kind() == reflect.Pointer { 587 typ = typ.Elem() 588 } 589 if typ.Kind() == reflect.Chan || typ.Kind() == reflect.Func { 590 return false 591 } 592 593 // Special case for Go 1.22: the x509.Certificate.Policies 594 // field is unencodable but also unused by default. 595 // Ignore it, so that x509.Certificate continues to be encodeable. 596 // Go 1.23 will add the right methods so that gob can 597 // handle the Policies field, and then we can remove this check. 598 // See go.dev/issue/65633. 599 if field.Name == "Policies" && struct_.PkgPath() == "crypto/x509" && struct_.Name() == "Certificate" { 600 return false 601 } 602 603 return true 604 } 605 606 // getBaseType returns the Gob type describing the given reflect.Type's base type. 607 // typeLock must be held. 608 func getBaseType(name string, rt reflect.Type) (gobType, error) { 609 ut := userType(rt) 610 return getType(name, ut, ut.base) 611 } 612 613 // getType returns the Gob type describing the given reflect.Type. 614 // Should be called only when handling GobEncoders/Decoders, 615 // which may be pointers. All other types are handled through the 616 // base type, never a pointer. 617 // typeLock must be held. 618 func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { 619 typ, present := types[rt] 620 if present { 621 return typ, nil 622 } 623 typ, err := newTypeObject(name, ut, rt) 624 if err == nil { 625 types[rt] = typ 626 } 627 return typ, err 628 } 629 630 func checkId(want, got typeId) { 631 if want != got { 632 fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) 633 panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) 634 } 635 } 636 637 // used for building the basic types; called only from init(). the incoming 638 // interface always refers to a pointer. 639 func bootstrapType(name string, e any) typeId { 640 rt := reflect.TypeOf(e).Elem() 641 _, present := types[rt] 642 if present { 643 panic("bootstrap type already present: " + name + ", " + rt.String()) 644 } 645 typ := &CommonType{Name: name} 646 types[rt] = typ 647 setTypeId(typ) 648 return typ.id() 649 } 650 651 // Representation of the information we send and receive about this type. 652 // Each value we send is preceded by its type definition: an encoded int. 653 // However, the very first time we send the value, we first send the pair 654 // (-id, wireType). 655 // For bootstrapping purposes, we assume that the recipient knows how 656 // to decode a wireType; it is exactly the wireType struct here, interpreted 657 // using the gob rules for sending a structure, except that we assume the 658 // ids for wireType and structType etc. are known. The relevant pieces 659 // are built in encode.go's init() function. 660 // To maintain binary compatibility, if you extend this type, always put 661 // the new fields last. 662 type wireType struct { 663 ArrayT *arrayType 664 SliceT *sliceType 665 StructT *structType 666 MapT *mapType 667 GobEncoderT *gobEncoderType 668 BinaryMarshalerT *gobEncoderType 669 TextMarshalerT *gobEncoderType 670 } 671 672 func (w *wireType) string() string { 673 const unknown = "unknown type" 674 if w == nil { 675 return unknown 676 } 677 switch { 678 case w.ArrayT != nil: 679 return w.ArrayT.Name 680 case w.SliceT != nil: 681 return w.SliceT.Name 682 case w.StructT != nil: 683 return w.StructT.Name 684 case w.MapT != nil: 685 return w.MapT.Name 686 case w.GobEncoderT != nil: 687 return w.GobEncoderT.Name 688 case w.BinaryMarshalerT != nil: 689 return w.BinaryMarshalerT.Name 690 case w.TextMarshalerT != nil: 691 return w.TextMarshalerT.Name 692 } 693 return unknown 694 } 695 696 type typeInfo struct { 697 id typeId 698 encInit sync.Mutex // protects creation of encoder 699 encoder atomic.Pointer[encEngine] 700 wire wireType 701 } 702 703 // typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo. 704 // It's updated copy-on-write. Readers just do an atomic load 705 // to get the current version of the map. Writers make a full copy of 706 // the map and atomically update the pointer to point to the new map. 707 // Under heavy read contention, this is significantly faster than a map 708 // protected by a mutex. 709 var typeInfoMap atomic.Value 710 711 // typeInfoMapInit is used instead of typeInfoMap during init time, 712 // as types are registered sequentially during init and we can save 713 // the overhead of making map copies. 714 // It is saved to typeInfoMap and set to nil before init finishes. 715 var typeInfoMapInit = make(map[reflect.Type]*typeInfo, 16) 716 717 func lookupTypeInfo(rt reflect.Type) *typeInfo { 718 if m := typeInfoMapInit; m != nil { 719 return m[rt] 720 } 721 m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) 722 return m[rt] 723 } 724 725 func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { 726 rt := ut.base 727 if ut.externalEnc != 0 { 728 // We want the user type, not the base type. 729 rt = ut.user 730 } 731 if info := lookupTypeInfo(rt); info != nil { 732 return info, nil 733 } 734 return buildTypeInfo(ut, rt) 735 } 736 737 // buildTypeInfo constructs the type information for the type 738 // and stores it in the type info map. 739 func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) { 740 typeLock.Lock() 741 defer typeLock.Unlock() 742 743 if info := lookupTypeInfo(rt); info != nil { 744 return info, nil 745 } 746 747 gt, err := getBaseType(rt.Name(), rt) 748 if err != nil { 749 return nil, err 750 } 751 info := &typeInfo{id: gt.id()} 752 753 if ut.externalEnc != 0 { 754 userType, err := getType(rt.Name(), ut, rt) 755 if err != nil { 756 return nil, err 757 } 758 gt := userType.id().gobType().(*gobEncoderType) 759 switch ut.externalEnc { 760 case xGob: 761 info.wire.GobEncoderT = gt 762 case xBinary: 763 info.wire.BinaryMarshalerT = gt 764 case xText: 765 info.wire.TextMarshalerT = gt 766 } 767 rt = ut.user 768 } else { 769 t := info.id.gobType() 770 switch typ := rt; typ.Kind() { 771 case reflect.Array: 772 info.wire.ArrayT = t.(*arrayType) 773 case reflect.Map: 774 info.wire.MapT = t.(*mapType) 775 case reflect.Slice: 776 // []byte == []uint8 is a special case handled separately 777 if typ.Elem().Kind() != reflect.Uint8 { 778 info.wire.SliceT = t.(*sliceType) 779 } 780 case reflect.Struct: 781 info.wire.StructT = t.(*structType) 782 } 783 } 784 785 if m := typeInfoMapInit; m != nil { 786 m[rt] = info 787 return info, nil 788 } 789 790 // Create new map with old contents plus new entry. 791 m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) 792 newm := make(map[reflect.Type]*typeInfo, len(m)) 793 for k, v := range m { 794 newm[k] = v 795 } 796 newm[rt] = info 797 typeInfoMap.Store(newm) 798 return info, nil 799 } 800 801 // Called only when a panic is acceptable and unexpected. 802 func mustGetTypeInfo(rt reflect.Type) *typeInfo { 803 t, err := getTypeInfo(userType(rt)) 804 if err != nil { 805 panic("getTypeInfo: " + err.Error()) 806 } 807 return t 808 } 809 810 // GobEncoder is the interface describing data that provides its own 811 // representation for encoding values for transmission to a GobDecoder. 812 // A type that implements GobEncoder and GobDecoder has complete 813 // control over the representation of its data and may therefore 814 // contain things such as private fields, channels, and functions, 815 // which are not usually transmissible in gob streams. 816 // 817 // Note: Since gobs can be stored permanently, it is good design 818 // to guarantee the encoding used by a GobEncoder is stable as the 819 // software evolves. For instance, it might make sense for GobEncode 820 // to include a version number in the encoding. 821 type GobEncoder interface { 822 // GobEncode returns a byte slice representing the encoding of the 823 // receiver for transmission to a GobDecoder, usually of the same 824 // concrete type. 825 GobEncode() ([]byte, error) 826 } 827 828 // GobDecoder is the interface describing data that provides its own 829 // routine for decoding transmitted values sent by a GobEncoder. 830 type GobDecoder interface { 831 // GobDecode overwrites the receiver, which must be a pointer, 832 // with the value represented by the byte slice, which was written 833 // by GobEncode, usually for the same concrete type. 834 GobDecode([]byte) error 835 } 836 837 var ( 838 nameToConcreteType sync.Map // map[string]reflect.Type 839 concreteTypeToName sync.Map // map[reflect.Type]string 840 ) 841 842 // RegisterName is like [Register] but uses the provided name rather than the 843 // type's default. 844 func RegisterName(name string, value any) { 845 if name == "" { 846 // reserved for nil 847 panic("attempt to register empty name") 848 } 849 850 ut := userType(reflect.TypeOf(value)) 851 852 // Check for incompatible duplicates. The name must refer to the 853 // same user type, and vice versa. 854 855 // Store the name and type provided by the user.... 856 if t, dup := nameToConcreteType.LoadOrStore(name, reflect.TypeOf(value)); dup && t != ut.user { 857 panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user)) 858 } 859 860 // but the flattened type in the type table, since that's what decode needs. 861 if n, dup := concreteTypeToName.LoadOrStore(ut.base, name); dup && n != name { 862 nameToConcreteType.Delete(name) 863 panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name)) 864 } 865 } 866 867 // Register records a type, identified by a value for that type, under its 868 // internal type name. That name will identify the concrete type of a value 869 // sent or received as an interface variable. Only types that will be 870 // transferred as implementations of interface values need to be registered. 871 // Expecting to be used only during initialization, it panics if the mapping 872 // between types and names is not a bijection. 873 func Register(value any) { 874 // Default to printed representation for unnamed types 875 rt := reflect.TypeOf(value) 876 name := rt.String() 877 878 // But for named types (or pointers to them), qualify with import path (but see inner comment). 879 // Dereference one pointer looking for a named type. 880 star := "" 881 if rt.Name() == "" { 882 if pt := rt; pt.Kind() == reflect.Pointer { 883 star = "*" 884 // NOTE: The following line should be rt = pt.Elem() to implement 885 // what the comment above claims, but fixing it would break compatibility 886 // with existing gobs. 887 // 888 // Given package p imported as "full/p" with these definitions: 889 // package p 890 // type T1 struct { ... } 891 // this table shows the intended and actual strings used by gob to 892 // name the types: 893 // 894 // Type Correct string Actual string 895 // 896 // T1 full/p.T1 full/p.T1 897 // *T1 *full/p.T1 *p.T1 898 // 899 // The missing full path cannot be fixed without breaking existing gob decoders. 900 rt = pt 901 } 902 } 903 if rt.Name() != "" { 904 if rt.PkgPath() == "" { 905 name = star + rt.Name() 906 } else { 907 name = star + rt.PkgPath() + "." + rt.Name() 908 } 909 } 910 911 RegisterName(name, value) 912 } 913 914 func registerBasics() { 915 Register(int(0)) 916 Register(int8(0)) 917 Register(int16(0)) 918 Register(int32(0)) 919 Register(int64(0)) 920 Register(uint(0)) 921 Register(uint8(0)) 922 Register(uint16(0)) 923 Register(uint32(0)) 924 Register(uint64(0)) 925 Register(float32(0)) 926 Register(float64(0)) 927 Register(complex64(0i)) 928 Register(complex128(0i)) 929 Register(uintptr(0)) 930 Register(false) 931 Register("") 932 Register([]byte(nil)) 933 Register([]int(nil)) 934 Register([]int8(nil)) 935 Register([]int16(nil)) 936 Register([]int32(nil)) 937 Register([]int64(nil)) 938 Register([]uint(nil)) 939 Register([]uint8(nil)) 940 Register([]uint16(nil)) 941 Register([]uint32(nil)) 942 Register([]uint64(nil)) 943 Register([]float32(nil)) 944 Register([]float64(nil)) 945 Register([]complex64(nil)) 946 Register([]complex128(nil)) 947 Register([]uintptr(nil)) 948 Register([]bool(nil)) 949 Register([]string(nil)) 950 } 951 952 func init() { 953 typeInfoMap.Store(typeInfoMapInit) 954 typeInfoMapInit = nil 955 }