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 5package gob 6 7import ( 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. 22type 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 33const ( 34 xGob = 1 + iota // GobEncoder or GobDecoder 35 xBinary // encoding.BinaryMarshaler or encoding.BinaryUnmarshaler 36 xText // encoding.TextMarshaler or encoding.TextUnmarshaler 37) 38 39var 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. 44func 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 105var ( 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. 120func 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. 153func 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. 163type typeId int32 164 165var typeLock sync.Mutex // set while building a type 166const firstUserId = 64 // lowest id number granted to user 167 168type 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 176var ( 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 182func idToType(id typeId) gobType { 183 if id < 0 || int(id) >= len(idToTypeSlice) { 184 return nil 185 } 186 return idToTypeSlice[id] 187} 188 189func builtinIdToType(id typeId) gobType { 190 if id < 0 || int(id) >= len(builtinIdToTypeSlice) { 191 return nil 192 } 193 return builtinIdToTypeSlice[id] 194} 195 196func 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 206func (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. 214func (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. 222func (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. 233type CommonType struct { 234 Name string 235 Id typeId 236} 237 238func (t *CommonType) id() typeId { return t.Id } 239 240func (t *CommonType) setId(id typeId) { t.Id = id } 241 242func (t *CommonType) string() string { return t.Name } 243 244func (t *CommonType) safeString(seen map[typeId]bool) string { 245 return t.Name 246} 247 248func (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 253var ( 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 276var tWireType = mustGetTypeInfo(wireTypeType).id 277var wireTypeUserInfo *userTypeInfo // userTypeInfo of wireType 278 279func 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 302type arrayType struct { 303 CommonType 304 Elem typeId 305 Len int 306} 307 308func newArrayType(name string) *arrayType { 309 a := &arrayType{CommonType{Name: name}, 0, 0} 310 return a 311} 312 313func (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 320func (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 328func (a *arrayType) string() string { return a.safeString(make(map[typeId]bool)) } 329 330// GobEncoder type (something that implements the GobEncoder interface) 331type gobEncoderType struct { 332 CommonType 333} 334 335func newGobEncoderType(name string) *gobEncoderType { 336 g := &gobEncoderType{CommonType{Name: name}} 337 setTypeId(g) 338 return g 339} 340 341func (g *gobEncoderType) safeString(seen map[typeId]bool) string { 342 return g.Name 343} 344 345func (g *gobEncoderType) string() string { return g.Name } 346 347// Map type 348type mapType struct { 349 CommonType 350 Key typeId 351 Elem typeId 352} 353 354func newMapType(name string) *mapType { 355 m := &mapType{CommonType{Name: name}, 0, 0} 356 return m 357} 358 359func (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 366func (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 376func (m *mapType) string() string { return m.safeString(make(map[typeId]bool)) } 377 378// Slice type 379type sliceType struct { 380 CommonType 381 Elem typeId 382} 383 384func newSliceType(name string) *sliceType { 385 s := &sliceType{CommonType{Name: name}, 0} 386 return s 387} 388 389func (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 400func (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 408func (s *sliceType) string() string { return s.safeString(make(map[typeId]bool)) } 409 410// Struct type 411type fieldType struct { 412 Name string 413 Id typeId 414} 415 416type structType struct { 417 CommonType 418 Field []fieldType 419} 420 421func (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 437func (s *structType) string() string { return s.safeString(make(map[typeId]bool)) } 438 439func 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. 452func 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(&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. 571func 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. 579func isSent(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 return true 594} 595 596// getBaseType returns the Gob type describing the given reflect.Type's base type. 597// typeLock must be held. 598func getBaseType(name string, rt reflect.Type) (gobType, error) { 599 ut := userType(rt) 600 return getType(name, ut, ut.base) 601} 602 603// getType returns the Gob type describing the given reflect.Type. 604// Should be called only when handling GobEncoders/Decoders, 605// which may be pointers. All other types are handled through the 606// base type, never a pointer. 607// typeLock must be held. 608func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) { 609 typ, present := types[rt] 610 if present { 611 return typ, nil 612 } 613 typ, err := newTypeObject(name, ut, rt) 614 if err == nil { 615 types[rt] = typ 616 } 617 return typ, err 618} 619 620func checkId(want, got typeId) { 621 if want != got { 622 fmt.Fprintf(os.Stderr, "checkId: %d should be %d\n", int(got), int(want)) 623 panic("bootstrap type wrong id: " + got.name() + " " + got.string() + " not " + want.string()) 624 } 625} 626 627// used for building the basic types; called only from init(). the incoming 628// interface always refers to a pointer. 629func bootstrapType(name string, e any) typeId { 630 rt := reflect.TypeOf(e).Elem() 631 _, present := types[rt] 632 if present { 633 panic("bootstrap type already present: " + name + ", " + rt.String()) 634 } 635 typ := &CommonType{Name: name} 636 types[rt] = typ 637 setTypeId(typ) 638 return typ.id() 639} 640 641// Representation of the information we send and receive about this type. 642// Each value we send is preceded by its type definition: an encoded int. 643// However, the very first time we send the value, we first send the pair 644// (-id, wireType). 645// For bootstrapping purposes, we assume that the recipient knows how 646// to decode a wireType; it is exactly the wireType struct here, interpreted 647// using the gob rules for sending a structure, except that we assume the 648// ids for wireType and structType etc. are known. The relevant pieces 649// are built in encode.go's init() function. 650// To maintain binary compatibility, if you extend this type, always put 651// the new fields last. 652type wireType struct { 653 ArrayT *arrayType 654 SliceT *sliceType 655 StructT *structType 656 MapT *mapType 657 GobEncoderT *gobEncoderType 658 BinaryMarshalerT *gobEncoderType 659 TextMarshalerT *gobEncoderType 660} 661 662func (w *wireType) string() string { 663 const unknown = "unknown type" 664 if w == nil { 665 return unknown 666 } 667 switch { 668 case w.ArrayT != nil: 669 return w.ArrayT.Name 670 case w.SliceT != nil: 671 return w.SliceT.Name 672 case w.StructT != nil: 673 return w.StructT.Name 674 case w.MapT != nil: 675 return w.MapT.Name 676 case w.GobEncoderT != nil: 677 return w.GobEncoderT.Name 678 case w.BinaryMarshalerT != nil: 679 return w.BinaryMarshalerT.Name 680 case w.TextMarshalerT != nil: 681 return w.TextMarshalerT.Name 682 } 683 return unknown 684} 685 686type typeInfo struct { 687 id typeId 688 encInit sync.Mutex // protects creation of encoder 689 encoder atomic.Pointer[encEngine] 690 wire wireType 691} 692 693// typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo. 694// It's updated copy-on-write. Readers just do an atomic load 695// to get the current version of the map. Writers make a full copy of 696// the map and atomically update the pointer to point to the new map. 697// Under heavy read contention, this is significantly faster than a map 698// protected by a mutex. 699var typeInfoMap atomic.Value 700 701// typeInfoMapInit is used instead of typeInfoMap during init time, 702// as types are registered sequentially during init and we can save 703// the overhead of making map copies. 704// It is saved to typeInfoMap and set to nil before init finishes. 705var typeInfoMapInit = make(map[reflect.Type]*typeInfo, 16) 706 707func lookupTypeInfo(rt reflect.Type) *typeInfo { 708 if m := typeInfoMapInit; m != nil { 709 return m[rt] 710 } 711 m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) 712 return m[rt] 713} 714 715func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { 716 rt := ut.base 717 if ut.externalEnc != 0 { 718 // We want the user type, not the base type. 719 rt = ut.user 720 } 721 if info := lookupTypeInfo(rt); info != nil { 722 return info, nil 723 } 724 return buildTypeInfo(ut, rt) 725} 726 727// buildTypeInfo constructs the type information for the type 728// and stores it in the type info map. 729func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) { 730 typeLock.Lock() 731 defer typeLock.Unlock() 732 733 if info := lookupTypeInfo(rt); info != nil { 734 return info, nil 735 } 736 737 gt, err := getBaseType(rt.Name(), rt) 738 if err != nil { 739 return nil, err 740 } 741 info := &typeInfo{id: gt.id()} 742 743 if ut.externalEnc != 0 { 744 userType, err := getType(rt.Name(), ut, rt) 745 if err != nil { 746 return nil, err 747 } 748 gt := userType.id().gobType().(*gobEncoderType) 749 switch ut.externalEnc { 750 case xGob: 751 info.wire.GobEncoderT = gt 752 case xBinary: 753 info.wire.BinaryMarshalerT = gt 754 case xText: 755 info.wire.TextMarshalerT = gt 756 } 757 rt = ut.user 758 } else { 759 t := info.id.gobType() 760 switch typ := rt; typ.Kind() { 761 case reflect.Array: 762 info.wire.ArrayT = t.(*arrayType) 763 case reflect.Map: 764 info.wire.MapT = t.(*mapType) 765 case reflect.Slice: 766 // []byte == []uint8 is a special case handled separately 767 if typ.Elem().Kind() != reflect.Uint8 { 768 info.wire.SliceT = t.(*sliceType) 769 } 770 case reflect.Struct: 771 info.wire.StructT = t.(*structType) 772 } 773 } 774 775 if m := typeInfoMapInit; m != nil { 776 m[rt] = info 777 return info, nil 778 } 779 780 // Create new map with old contents plus new entry. 781 m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) 782 newm := make(map[reflect.Type]*typeInfo, len(m)) 783 for k, v := range m { 784 newm[k] = v 785 } 786 newm[rt] = info 787 typeInfoMap.Store(newm) 788 return info, nil 789} 790 791// Called only when a panic is acceptable and unexpected. 792func mustGetTypeInfo(rt reflect.Type) *typeInfo { 793 t, err := getTypeInfo(userType(rt)) 794 if err != nil { 795 panic("getTypeInfo: " + err.Error()) 796 } 797 return t 798} 799 800// GobEncoder is the interface describing data that provides its own 801// representation for encoding values for transmission to a GobDecoder. 802// A type that implements GobEncoder and GobDecoder has complete 803// control over the representation of its data and may therefore 804// contain things such as private fields, channels, and functions, 805// which are not usually transmissible in gob streams. 806// 807// Note: Since gobs can be stored permanently, it is good design 808// to guarantee the encoding used by a GobEncoder is stable as the 809// software evolves. For instance, it might make sense for GobEncode 810// to include a version number in the encoding. 811type GobEncoder interface { 812 // GobEncode returns a byte slice representing the encoding of the 813 // receiver for transmission to a GobDecoder, usually of the same 814 // concrete type. 815 GobEncode() ([]byte, error) 816} 817 818// GobDecoder is the interface describing data that provides its own 819// routine for decoding transmitted values sent by a GobEncoder. 820type GobDecoder interface { 821 // GobDecode overwrites the receiver, which must be a pointer, 822 // with the value represented by the byte slice, which was written 823 // by GobEncode, usually for the same concrete type. 824 GobDecode([]byte) error 825} 826 827var ( 828 nameToConcreteType sync.Map // map[string]reflect.Type 829 concreteTypeToName sync.Map // map[reflect.Type]string 830) 831 832// RegisterName is like [Register] but uses the provided name rather than the 833// type's default. 834func RegisterName(name string, value any) { 835 if name == "" { 836 // reserved for nil 837 panic("attempt to register empty name") 838 } 839 840 ut := userType(reflect.TypeOf(value)) 841 842 // Check for incompatible duplicates. The name must refer to the 843 // same user type, and vice versa. 844 845 // Store the name and type provided by the user.... 846 if t, dup := nameToConcreteType.LoadOrStore(name, reflect.TypeOf(value)); dup && t != ut.user { 847 panic(fmt.Sprintf("gob: registering duplicate types for %q: %s != %s", name, t, ut.user)) 848 } 849 850 // but the flattened type in the type table, since that's what decode needs. 851 if n, dup := concreteTypeToName.LoadOrStore(ut.base, name); dup && n != name { 852 nameToConcreteType.Delete(name) 853 panic(fmt.Sprintf("gob: registering duplicate names for %s: %q != %q", ut.user, n, name)) 854 } 855} 856 857// Register records a type, identified by a value for that type, under its 858// internal type name. That name will identify the concrete type of a value 859// sent or received as an interface variable. Only types that will be 860// transferred as implementations of interface values need to be registered. 861// Expecting to be used only during initialization, it panics if the mapping 862// between types and names is not a bijection. 863func Register(value any) { 864 // Default to printed representation for unnamed types 865 rt := reflect.TypeOf(value) 866 name := rt.String() 867 868 // But for named types (or pointers to them), qualify with import path (but see inner comment). 869 // Dereference one pointer looking for a named type. 870 star := "" 871 if rt.Name() == "" { 872 if pt := rt; pt.Kind() == reflect.Pointer { 873 star = "*" 874 // NOTE: The following line should be rt = pt.Elem() to implement 875 // what the comment above claims, but fixing it would break compatibility 876 // with existing gobs. 877 // 878 // Given package p imported as "full/p" with these definitions: 879 // package p 880 // type T1 struct { ... } 881 // this table shows the intended and actual strings used by gob to 882 // name the types: 883 // 884 // Type Correct string Actual string 885 // 886 // T1 full/p.T1 full/p.T1 887 // *T1 *full/p.T1 *p.T1 888 // 889 // The missing full path cannot be fixed without breaking existing gob decoders. 890 rt = pt 891 } 892 } 893 if rt.Name() != "" { 894 if rt.PkgPath() == "" { 895 name = star + rt.Name() 896 } else { 897 name = star + rt.PkgPath() + "." + rt.Name() 898 } 899 } 900 901 RegisterName(name, value) 902} 903 904func registerBasics() { 905 Register(int(0)) 906 Register(int8(0)) 907 Register(int16(0)) 908 Register(int32(0)) 909 Register(int64(0)) 910 Register(uint(0)) 911 Register(uint8(0)) 912 Register(uint16(0)) 913 Register(uint32(0)) 914 Register(uint64(0)) 915 Register(float32(0)) 916 Register(float64(0)) 917 Register(complex64(0i)) 918 Register(complex128(0i)) 919 Register(uintptr(0)) 920 Register(false) 921 Register("") 922 Register([]byte(nil)) 923 Register([]int(nil)) 924 Register([]int8(nil)) 925 Register([]int16(nil)) 926 Register([]int32(nil)) 927 Register([]int64(nil)) 928 Register([]uint(nil)) 929 Register([]uint8(nil)) 930 Register([]uint16(nil)) 931 Register([]uint32(nil)) 932 Register([]uint64(nil)) 933 Register([]float32(nil)) 934 Register([]float64(nil)) 935 Register([]complex64(nil)) 936 Register([]complex128(nil)) 937 Register([]uintptr(nil)) 938 Register([]bool(nil)) 939 Register([]string(nil)) 940} 941 942func init() { 943 typeInfoMap.Store(typeInfoMapInit) 944 typeInfoMapInit = nil 945} 946